C# 调用 C dll char* callback 设置回调函数不定参数

1:C# 调用 返回 字符串 C++ native dll 函数 的注意事项:

a:C++ DLL的返回值,安全的做法是分配一个全局 char 数组,把要返回的 char * 复制到这个 char 数组中,

 

char   buff[255];    

const char* __stdcall ReturnString()
{
  strcpy(buff,"xxxxxxxxxxxxxxx");
  return buff;
 }

b:C# 收到 字符串后,需要 Marshal

[DllImport("VC.dll",   CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
public static extern IntPtr ReturnString();

//调用VCDLL的代码...

IntPtr intPtr = ReturnString();

string str = Marshal.PtrToStringAnsi(intPtr);

...

因为 C++ 返回的是 char* ,是个指针,所以c# 要用 IntPtr 来接回。

Marshal.PtrToStringAnsi MSDN上的解释:将非托管 ANSI 字符串中第一个空值(空值就是\0)之前的所有字符复制到托管 String。将每个 ANSI 字符扩展为 Unicode 字符。

 

2:用参数传递,即C++dll 函数的参数 定义为 char*,而C#传递 StringBuilder 给 c++

a:c# 创建一个 StringBuilder,并初始化 capacity后传给C++

[DllImport("VC.dll",  CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
public static extern void ProcessString(StringBuilder str);

//调用VCDLL的代码...

StringBuilder str = new StringBuilder(255); //255 是 capacity

ProcessString(str);

MessageBox.Show(str); //不需要Marshal,直接使用

...

 

b:C++ DLL函数

const char* __stdcall ProcessString(char* str)
{

  //str 是 c# 创建的 StringBuilder,长度是255
  strcpy(str,"xxxxxxxxxxxxxxx");
  return buff;
}

其他的请参考msdn中的c++与c#的类型转换 对应关系如下:

 C++ ---- C#

传入的char*  ----string

传出的char* ---- StringBuilder(预分配空间)

short  ----short

char ---- byte

char[n] ---- fixed byte[n]

结构指针  ----结构指针

函数指针 ---- 委托


CallBack

C++代码:

    void SetCallback(CPPCallback callback)  
    {  
        char *p = "from C++";  
        callback(p);  
    }  

C#代码

[DllImport("DLLTest")]  
 private static extern void SetCallback( CSCallback callback );  
  
 public delegate void CSCallback( IntPtr num );  
 static CSCallback callback;  
  
 void Start()  
 {  
     callback = CSCallbackFunction;  
 }  
  
 static void CSCallbackFunction( IntPtr num )  
 {  
     string str = Marshal.PtrToStringAnsi( num );  
     Debug.Log("====== " + str);  
 } 
可以用了:

 调用 SetCallback(callback); 

三。 C 中允许设置函数参数个数不定方便扩展如: typedef void (  *CallbackFun)(const int Model,...);

用来设置回调,哪么可能在C#必须要有多个函数;

在使用时注意:

导出接口时,同一接口要导出多次,填入不出的指针例:

    [DllImportAttribute("dll_VR_usVcl.dll", EntryPoint = "SetCallBackFun", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
        public extern static int XHXY_SetCallBackFunMode([MarshalAs(UnmanagedType.FunctionPtr)]CallbackFun callback_f, int type);

        public delegate void CallbackFun(int mode);
        static CallbackFun callback;
        [DllImportAttribute("dll_VR_usVcl.dll", EntryPoint = "SetCallBackFun", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
        public extern static int SetCallBackFunInfo([MarshalAs(UnmanagedType.FunctionPtr)]CallbackFunInfo callback_f, int type);
        public delegate void CallbackFunInfo(int mode, IntPtr userinfo);

        static CallbackFunInfo callbackinfo;
            
        void Start()
        {
            callback = CSCallbackFun;
            callbackinfo = CSCallbackFunInfo;
        }

   
        static void CSCallbackFun(int mode)
        {
           
            System.Console.Write("CallbackFun mode " + mode);
        }

        static void CSCallbackFunInfo(int mode, IntPtr userinfo)
        {
            string info = userinfo.ToString();//Marshal.PtrToStringAnsi(userinfo);
            System.Console.Write("CallbackFun mode " + mode + "userinfo " + info);
        }



你可能感兴趣的:(C/C++)