首页 > 编程语言 >C# 调用 C dll char* callback 设置回调函数不定参数

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

时间:2023-05-01 16:03:24浏览次数:45  
标签:C# void dll char callback int static str


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);
        }





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#,void,dll,char,callback,int,static,str
From: https://blog.51cto.com/u_12389088/6238949

相关文章

  • doceker 安装
     CentOSDocker安装Docker支持以下的CentOS版本:CentOS7(64-bit)CentOS6.5(64-bit)或更高的版本 前提条件目前,CentOS仅发行版本中的内核支持Docker。Docker运行在CentOS7上,要求系统为64位、系统内核版本为3.10以上。Docker运行在CentOS-6.5或更高的版本的Ce......
  • centos7 安装centos桌面
    一、输入命令yumgroupinstall"GNOMEDesktop""GraphicalAdministrationTools"二、设置系统启动等级。systemctlget-default#获取当前系统运行形式,会显示multi-user.target(命令行终端),或者:graphical.targetsystemctlset-defaultgraphical.target#设置默认启动为图形界面,re......
  • HTML5+CSS3
    CSS3HTMLHTML总结......
  • Elasticsearch专题精讲——What is Elasticsearch?
    WhatisElasticsearch?https://www.elastic.co/guide/en/elasticsearch/reference/8.7/elasticsearch-intro.html ElasticsearchisthedistributedsearchandanalyticsengineattheheartoftheElasticStack.LogstashandBeatsfacilitatecollecting,aggrega......
  • [ABC146F] Sugoroku
    2023-03-03题目题目传送门翻译翻译难度&重要性(1~10):5题目来源AtCoder题目算法贪心解题思路对于第ii个点,只要到达\(s_{i+1}\cdotss_{i+m}\)中最后一个\(0\)的位置。但是这种方法求出的字典序肯定是最大的,但题目要求的是字典序最小。那么就可以倒序枚举,使第\(......
  • 利用 docker 搭建 registry 私有仓库
    搭建环境:Debian11(bullseye)1.安装docker并配置镜像加速器下载安装:https://docs.docker.com/engine/install/debian/镜像加速器配置:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors2.下载registry镜像 3.配置https证书#创建证书存放目录mkdir......
  • Codeforces Round 869 (Div. 2)
    Preface一把回到紫名还是很舒服的,D题手比较稳猜了点性质水过主要还是C脑抽了想了挺久才看出来是个丁真题,不然最后过了D之后30min可以看看E的由于要写学校的图论专题所以接下来一段时间的CF补题计划就要先停一停了A.Politics傻逼题,当某个人的串和第一个人有任意一个位置不同......
  • [ABC145F] Laminate
    2023-02-25题目题目传送门翻译翻译难度&重要性(1~10):6题目来源AtCoder题目算法dp解题思路引子:积木大赛可以发现当\(k=1\)时,就是积木大赛。该列比前一列高:此时会产生\(h_i-h_{i-1}\)的贡献。该列比前一列矮或相等:此时不会产生贡献。但是如果后面那列比前面......
  • VC程序Release程序崩溃后问题根源查找
    Part1.如何去做崩溃后的定位是一个有效的方法。1.可以先利用连接器的配置,产生map文件:在VCProjectSetting对话框中打开Generatemapfile,然后在ProjectOptions对话框中键入“/mapinfo:lines/mapinfo:exports”,这样在./release目录下就有.pdb文件了。然后在配合这个......
  • Centos7 安装 python3.9
    今天差点把服务器搞砖了,3.6无法满足要求,3.7一直装不上。重装之前遇到这篇文章,搞定Centos7系统安装Python3.9图文教程......