ネイティブライブラリ用のC#ラッパーを作成しています。これは、このコールバック関数が含まれています構造体パラメータへのポインタを持つC#ネイティブコールバック
typedef application_event_result(*application_event_ptr)(application_request* request);
パラメータは、このような次のように定義されますC#で
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate application_event_result application_event([MarshalAs(UnmanagedType.Struct)]
ref application_request request);
構造:
typedef struct {
uint32_t query;
const char* client;
bool isAuthenticated;
bool isGuest;
} application_request;
私はこのようなC#のコールバックデリゲートを定義しています
[StructLayout(LayoutKind.Sequential)]
public struct application_request
{
public UInt32 query;
[MarshalAs(UnmanagedType.LPStr)]
public string client;
[MarshalAs(UnmanagedType.I1)]
public bool isAuthenticated;
[MarshalAs(UnmanagedType.I1)]
public bool isGuest;
}
このすべてのはと思われます。 C#のコールバックがトリガされ、構造体のメンバーは期待値を持ちます。
しかし、ネイティブコードに戻ると、ヒープ破損例外が発生します(0xc0000374)。
明らかに、私はそれを避けたいと思います。
"ref application_request"パラメータの代わりにIntPtrを使用するようにC#コールバックシグネチャを変更した後、次のコードを使用して手動でマーシャリングします。
var request = Marshal.PtrToStructure<application_request>(requestptr);
しかし、署名をできるだけ正確にしたいと思い、マーシャラを自分で使用する必要はありません。
コールバックデリゲートのシグネチャを変更しても構わないので、.netは自動的に構造体を変換できますか?
returnパラメータのサイズが一貫していないため、エラーが発生しています。 IntPtrは4バイトなので、C#で4バイトのリターンパラメータを宣言する必要があります。ポインターの位置は、cとC#コードが一緒に動作するためには、静的メモリースペース内にある必要があります。 IntPtrはアンマネージスタティックメモリ空間にあるため、動作します。 C#オブジェクトが管理され、アンマネージ空間に置かれた場合にエラーが発生します。 – jdweng
問題は戻り値ではなく、ポインターから構造体への入力パラメーターを使用しています。それをマークしてアンマネージドスペースに入れる方法はありますか? – RasmusW
@jdweng戻り値は列挙型のように見えませんか? –