C#のC / C ++ DLLでネストされた構造体ポインターを使用する

arash javan

C-langで記述されたdllに次のコードがあるとしましょう。ここで、dllで定義されたいくつかの関数を関数ポインターとしてマップし、実際の関数にマップしようとします。次のリンクをたどって、ここまで到達しますhttps://docs.microsoft .com / en-us / dotnet / framework / interop / marshaling-different-types-of-arrays

Dlltest.h

typedef struct VersionInfo
{
  UINT uMajor;
  UINT uMinor;
  UINT uMRevision;
} STRUCT_VERSION_INFO;

typedef struct DllTestFPStruct
{
  int(*Close) (void);
  int(*Init) (STRUCT_VERSION_INFO *sVersInfo);
  int(*RegisterClient) (int id);
} STRUCT_DLL_TEST_FP_STRUCT;

typedef struct DllTestMgr
{
  STRUCT_DLL_TEST_FP_STRUCT *psItf;
  int iDummy;
} STRUCT_DLL_TEST_MGR;

extern "C"
{ __declspec(dllexport) void GetDllTestFP(STRUCT_DLL_TEST_MGR *psFP); }

Dlltest.c

static int Close(void);
static int Init(STRUCT_VERSION_INFO *sVersInfo);
static int RegisterClient(int id);

STRUCT_DLL_TEST_FP_STRUCT sFP =
{
  &Close,
  &Init,
  &RegisterClient,
};

DLLTESTC_API void GetDllTestFP(STRUCT_DLL_TEST_MGR *psFP)
{ psFP->psItf = &sFP; }

static int Close(void)
{ printf("Closed called.\n"); }

static int Init(STRUCT_VERSION_INFO *sVersInfo)
{ printf("Init called.\n");}

static int RegisterClient(STRUCT_VERSION_INFO *sVersInfo)
{  printf("RegisterClient called.\n");}

ここで、このDLLを使用するac#アプリケーションを作成したいと思います。特に、「GetDllTestFP」(関数ポインターを実際の関数にマップする関数)を使用する必要があります。現在、私のC#アプリケーションは次のとおりです。

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate int FP_DLL_TEST_CLOSE(ref VersionInfo sVersInfo);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate int FP_DLL_TEST_INIT(ref VersionInfo sVersInfo);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate int FP_DLL_TEST_RC(ref VersionInfo sVersInfo);

    [StructLayout(LayoutKind.Sequential)]
    public struct DllTestFPStruct
    {
        public FP_DLL_TEST_CLOSE Close;   
        public FP_DLL_TEST_INIT Init;
        public FP_DLL_TEST_RC RegisterClient;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct DllTestMgr
    {
        public IntPtr psItf;
        public int iDummy;
    }

    [DllImport("DllTestC.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
    public static extern void GetDllTestFP(ref DllTestMgr ps);

    static void Main(string[] args)
    {
        VersionInfo vInfo = new VersionInfo();
        DllTestFPStruct dllFPs = new DllTestFPStruct();
        DllTestMgr dllTest = new DllTestMgr();
        IntPtr buffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(dllFPs));
        Marshal.StructureToPtr(dllFPs, buffer, false);
        dllTest.psItf = buffer;
        GetDllTestFP(ref dllTest);  // Funtionpointers are not mapped, still null
        dllFPs.Close(ref vInfo);
  }

問題は、関数がdll内の実際の関数にマップされないことです。どうすれば目標を達成できますか?

ありがとう

ザナトス

C#コードは次のとおりです。

DllTestMgr dllTest = new DllTestMgr();
GetDllTestFP(ref dllTest);
DllTestFPStruct dllFPs = (DllTestFPStruct)Marshal.PtrToStructure(dllTest.psItf, typeof(DllTestFPStruct));

VersionInfo vInfo = new VersionInfo();
dllFPs.Close(ref vInfo);

次のように、dllTest.psItfbecaseを割り当てる必要はありGetDllTestFPません。

DLLTESTC_API void GetDllTestFP(STRUCT_DLL_TEST_MGR *psFP)
{
    psFP->psItf = &sFP;
}

だから、コピーしたアドレスのをsFP

データ(sFP構造体)への直接アクセスを「クライアント」に与えるため、一般的にこれは悪い考えであることに注意してください別の方法は、クライアントが(前に書いたように)メモリを渡してから、次のことを行うことです。

(*psFP->psItf) = sFP; 

(ただし、割り当てられたメモリを解放することを忘れないでください!)

3番目の方法として、C側は共有アロケーター(C#で使用できるため、ここでmalloc/newここでは使用できません)を介してメモリブロックを割り当て、C#はそれを割り当て解除する必要があります。

間違った解決策は

STRUCT_DLL_TEST_FP_STRUCT sFP2 = sFP;
psFP->psItf = &sFP2;

の存続期間はsFP2、メソッドが戻るとき終了します。psFP->psItfは、もう存在しないスタックの一部を指しています。しないでください!

ああ... @Hansアンパッサンによって書かれたように、メモリを割り当て、誰に応じて、GetDllTestFP可能refoutメモリがC#によって割り当てられている場合は、ref(現在のように)割り当てられていないか、C ++によって割り当てられている場合は、問題outありません。一方向のマーシャリングを節約できます。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

Cでネストされた構造体ポインタのコードを生成する

分類Dev

Cで構造体なしでネストされたダブルポインタを作成するにはどうすればよいですか?

分類Dev

C構造体定義内にネストされたポインターがあるのはなぜですか?

分類Dev

構造体ポインタと指定された初期化を使用してC構造体を初期化する方法

分類Dev

Cの構造体で使用される関数ポインタ

分類Dev

Cを使用してネストされた構造体のデータを変更する

分類Dev

「警告:ポインタと整数の比較」と言っているCのネストされた構造体

分類Dev

Cでvoidポインタにキャストされた構造体サイズを知る方法は?

分類Dev

ネストされた構造体ポインターを使用したCセグメンテーション違反

分類Dev

C#ツリービューをネストされた構造のリストにバインドする

分類Dev

C の構造体でポインタを使用する方法

分類Dev

C#は、構造体(非ブリット可能な型を含む)へのポインターをアンマネージC ++ DLLに渡します

分類Dev

Cで構造体のポインタをコピーする

分類Dev

malloc-expressionの予期されるエラーCを使用した構造体へのポインター

分類Dev

Cでネストされた構造体で指定されたinitを使用する方法は?

分類Dev

C ++で動的サイズのネストされた構造体

分類Dev

Cのポインタを持つネストされた構造

分類Dev

Swiftはcで定義された構造体のダブルポインターを定義します

分類Dev

Cで前方宣言された構造体の配列へのポインター

分類Dev

C#とCの間のネストされた構造体のマーシャリング-Simple HelloWorld

分類Dev

C-コンストラクター、構造体または構造体へのポインターを返す方が良いですか?

分類Dev

C言語:ネストされた構造体でchar配列を参照する

分類Dev

C++ でネストされた構造体をパックする

分類Dev

ユニオンを使用したネストされた構造体のC ++からC#へのマーシャリング

分類Dev

構造体のベクトルを介したc ++ネストされたイテレータの問題

分類Dev

Cのポインタを使用した構造体のバブルソート

分類Dev

C ++ protobufネストされた構造体の値を設定する方法

分類Dev

C#でネストされたjson構造内のキーと値のペアを削除する方法

分類Dev

構造タイプパラメーターを使用してc ++ dllのエクスポートされた関数を呼び出すPowerShell

Related 関連記事

  1. 1

    Cでネストされた構造体ポインタのコードを生成する

  2. 2

    Cで構造体なしでネストされたダブルポインタを作成するにはどうすればよいですか?

  3. 3

    C構造体定義内にネストされたポインターがあるのはなぜですか?

  4. 4

    構造体ポインタと指定された初期化を使用してC構造体を初期化する方法

  5. 5

    Cの構造体で使用される関数ポインタ

  6. 6

    Cを使用してネストされた構造体のデータを変更する

  7. 7

    「警告:ポインタと整数の比較」と言っているCのネストされた構造体

  8. 8

    Cでvoidポインタにキャストされた構造体サイズを知る方法は?

  9. 9

    ネストされた構造体ポインターを使用したCセグメンテーション違反

  10. 10

    C#ツリービューをネストされた構造のリストにバインドする

  11. 11

    C の構造体でポインタを使用する方法

  12. 12

    C#は、構造体(非ブリット可能な型を含む)へのポインターをアンマネージC ++ DLLに渡します

  13. 13

    Cで構造体のポインタをコピーする

  14. 14

    malloc-expressionの予期されるエラーCを使用した構造体へのポインター

  15. 15

    Cでネストされた構造体で指定されたinitを使用する方法は?

  16. 16

    C ++で動的サイズのネストされた構造体

  17. 17

    Cのポインタを持つネストされた構造

  18. 18

    Swiftはcで定義された構造体のダブルポインターを定義します

  19. 19

    Cで前方宣言された構造体の配列へのポインター

  20. 20

    C#とCの間のネストされた構造体のマーシャリング-Simple HelloWorld

  21. 21

    C-コンストラクター、構造体または構造体へのポインターを返す方が良いですか?

  22. 22

    C言語:ネストされた構造体でchar配列を参照する

  23. 23

    C++ でネストされた構造体をパックする

  24. 24

    ユニオンを使用したネストされた構造体のC ++からC#へのマーシャリング

  25. 25

    構造体のベクトルを介したc ++ネストされたイテレータの問題

  26. 26

    Cのポインタを使用した構造体のバブルソート

  27. 27

    C ++ protobufネストされた構造体の値を設定する方法

  28. 28

    C#でネストされたjson構造内のキーと値のペアを削除する方法

  29. 29

    構造タイプパラメーターを使用してc ++ dllのエクスポートされた関数を呼び出すPowerShell

ホットタグ

アーカイブ