C#でC++を呼び出すdllのパラメータがポインタタイプの導出関数(二次ポインタの場合を含む)

7463 ワード

厳密にはC++の範囲ではありませんが、少し縁を切って、自分のブログに記録しておきましょう.C++にポインタを使うのは日常茶飯事で、とても使いやすいです.これも私がC++が好きな理由の一つです.しかしC#では管理の概念を強調しており、ポインタは考えなくてもいい.もともとC#の世界の中でコードを书くならば、まだ心地よくて、しかし万事万物はいつも连络があって、これはいいえ、今会社のもう一つのC#で作るプロジェクトは问题にぶつかって、呼び出す前にC++で书く1つのDLLの中のいくつかの関数を使って、多くの関数のパラメータはすべて指针のタイプで、これは面倒ですね、会社の中でC#をするのはすべて始まったばかりで、C++は私が最もよく知っているだけで、この技術研究の仕事は光栄にも私に落ちました.私はC#にもあまり詳しくないので、私の方法が最も直接的ではないかもしれませんが、テストの結果はこの呼び出しの必要性を満たしています.以下、詳しく紹介します.unsafe、fixなどのキーワードを使うと実現できるはずですが、彼らのプロジェクトチームはこれを使わないことを要求しているので、私も深く試験していません.この方法に加えて、2つの考え方があるはずです.1つ目の考え方は直接的に見えるかもしれませんが、refを使うと、refというキーワードは少し特殊なようです.字面的にはC++の引用タイプに対応すべきだと理解されていますが、それはまだ一定の特殊性があるようです.以前、refが自分で引用タイプなのかポインタなのかを判断する文章を見たことがあるようです.試してみましたが、やはり可能です.しかし、二次ポインタがある場合refも機能しなくなります~これは私のもう一つの考え方を導き出して、Marshalを使います.次に、C++DLLのコード断片を説明します.主に使用される2つの構造の定義と、関数TestFunctionの定義をエクスポートします.
 
 
C++ DLL      
#pragma pack(push)
#pragma pack(1)
typedef struct EmmStruct {
    int len;
} EMMSTRUCT, *LPEMMSTRUCT;

typedef struct MyStruct {
    int iParam;
    long size;
    LPEMMSTRUCT lpEmmStructArr;
} MYSTRUCT, *LPMYSTRUCT;
#pragma pack(pop)

extern "C" void __declspec(dllexport) __stdcall  TestFunction(LPMYSTRUCT lpMyStruct)
{
    lpMyStruct->iParam = 100;
    lpMyStruct->size = 10;
    lpMyStruct->lpEmmStructArr = new EMMSTRUCT[lpMyStruct->size];
    for(int i=0;isize;i++) {
        lpMyStruct->lpEmmStructArr[i].len = i;
    }
}

      C#      :
C#        using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;      //  C#  dll   

namespace csharptest
{
    //StructLayout FieldOffset         ,               ,              
    [StructLayout(LayoutKind.Explicit)]
    public struct EmmStruct
    {
        [FieldOffset(0)]
        public int len;
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct MyStruct
    {
        [FieldOffset(0)]
        public int iParam;
        [FieldOffset(4)]
        public int size;
        [FieldOffset(8)]
        public IntPtr ptrEmmStruct;
    }

    class Program
    {
         // dll        
        [DllImport("dllforcsharp.dll", CallingConvention=CallingConvention.Winapi)]
        public extern static void TestFunction(IntPtr ptr);

        static void Main(string[] args)
        {
            try
            {
                MyStruct s = new MyStruct();
                IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(s));
                Marshal.StructureToPtr(s, ptr, false);

                TestFunction(ptr);

                s = (MyStruct)Marshal.PtrToStructure(ptr, typeof(MyStruct));

                EmmStruct ret;
                for (int i = 0; i < s.size; i++)
                {
                    IntPtr ptr2 = new IntPtr(s.ptrEmmStruct.ToInt32() + 4 * i);
                    ret = (EmmStruct)Marshal.PtrToStructure(ptr2, typeof(EmmStruct));
                }

                Marshal.FreeHGlobal(ptr);
            }
            catch (Exception e)
            {
                string str = e.Message;
            }
            finally
            {
            }
        }
    }
}

     ,                  ,        。                     。      C#  long C++   ,  8  。       C++ long ,C#   int  int32 ok 。    C#      ,             ,        ,       ,      。
        

 
転載先:https://www.cnblogs.com/profession/p/4914439.html