找回密码
 立即注册
首页 资源区 代码 简单写一个C函数供C#代码调用

简单写一个C函数供C#代码调用

岑韬哎 2025-5-29 10:52:56
在C#中调用C++动态库导出的函数时,有时候需要封送一些复杂的数据结构,这时候不确定自己封送的数据的内存布局对不对,就想要弄个简单的C++项目模拟一下被调用的接口,检查一下C#的数据封送是否正确。
因为对C++项目基本上没任何了解,捣鼓了半天才搞定,所以这里简单记录一下过程,以加深记忆。
1. 首先用C++的动态链接库模板创建一个项目。然后在dllmain.cpp中定义一个名为PostMsg的C导出函数,该函数接收MsgData结构体并打印,代码如下:
  1. typedef struct MsgData
  2. {
  3.     int index;
  4.     char msg[32];
  5.     BYTE data[8];
  6. } MsgData;
  7. static void dumpData(const MsgData* msg)
  8. {
  9.     for (size_t i = 0; i < sizeof(msg->data); i++)
  10.     {
  11.         printf("%02x ", *(msg->data + i));
  12.         if ((i + 1) % 8 == 0)
  13.         {
  14.             printf("\n");
  15.         }
  16.     }
  17. }
  18. extern "C"
  19. __declspec(dllexport) void PostMsg(MsgData* msg)
  20. {
  21.     printf("index=%d\nmsg="%s"\n", msg->index, msg->msg);
  22.     dumpData(msg);
  23. }
复制代码
 
2. 然后创建一个C#的控制台程序来调用它。这里通过DllImport特性来导入C++项目的PostMsg函数,同样也定义了对应的MsgData结构体,代码如下:
  1. var msg = new Msg.MsgData()
  2. {
  3.     Index = 2025,
  4.     Msg = "custom msg",
  5.     Data = [1,2,3,4,5,6,7,8]
  6. };
  7. var ptr = Marshal.AllocHGlobal(Marshal.SizeOf<Msg.MsgData>());
  8. Marshal.StructureToPtr(msg, ptr, false);
  9. Msg.PostMsg(ptr);
  10. internal class Msg
  11. {
  12.     [DllImport("TestDll.dll", EntryPoint = "PostMsg")]
  13.     public static extern void PostMsg(IntPtr msg);
  14.     [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
  15.     public struct MsgData
  16.     {
  17.         public int Index;
  18.         [MarshalAs(UnmanagedType.ByValTStr,SizeConst = 32)]
  19.         public string Msg;
  20.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
  21.         public byte[] Data;
  22.     }
  23. }
复制代码
 
3. 接着将C++项目添加为C#项目的项目引用。
1.png

 这里存在一个问题,C#项目不支持添加C++的项目引用,所以这里标了黄色感叹号,虽然构建C#项目的时候会先构建C++项目,但不会自动把C++项目的输出拷贝到C#项目的输出目录。
网上有很多方法能够解决把C++输出拷贝到C#输出目录的问题,我这里采用添加项目文件的方式,在C#的项目文件里添加以下内容:
  1.   <ItemGroup>
  2.       <None Include="../x64/$(Configuration)/*.dll;../x64/$(Configuration)/*.pdb">
  3.       <CopyToOutputDirectory>Always</CopyToOutputDirectory>      
  4.     </None>
  5.   </ItemGroup>
复制代码
 
4. 最后看一下结果:
  1. index=2025
  2. msg="custom msg"
  3. 01 02 03 04 05 06 07 08
复制代码
结果正常,这样就可以简单验证一下自己往C函数里封送的数据是不是正确了

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册