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

这里存在一个问题,C#项目不支持添加C++的项目引用,所以这里标了黄色感叹号,虽然构建C#项目的时候会先构建C++项目,但不会自动把C++项目的输出拷贝到C#项目的输出目录。
网上有很多方法能够解决把C++输出拷贝到C#输出目录的问题,我这里采用添加项目文件的方式,在C#的项目文件里添加以下内容:
<ItemGroup>
<None Include="../x64/$(Configuration)/*.dll;../x64/$(Configuration)/*.pdb">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
4. 最后看一下结果:
index=2025
msg="custom msg"
01 02 03 04 05 06 07 08
结果正常,这样就可以简单验证一下自己往C函数里封送的数据是不是正确了
简单写一个C函数供C#代码调用的更多相关文章
- 请写一个php函数,可以接受任意数量的参数
请写一个php函数,可以接受任意数量的参数 这是一道面试题.怎么写这个函数呢? function fun(......) { } ----------------------------------- ...
- 自己写一个strcmp函数(C++)
题目说明: 写一个函数,实现两个字符串的比较.即自己写一个strcmp函数,函数原型为int strcmp( char * p1, char * p2); 设p1指向字符串s1,p2指向字符串s2.要 ...
- 写一个PHP函数,实现扫描并打印出指定目录下(含子目录)的所有jpg文件名
写一个PHP函数,实现扫描并打印出指定目录下(含子目录)的所有jpg文件名 <?php $dir = "E:\照片\\";//打印文件夹中所有jpg文件 function p ...
- 034-PHP简单定义一个匿名函数
<?php /* 简单定义一个匿名函数 */ # 把匿名函数赋值给一个变量,也叫临时函数 $demo = function ($txt) { echo $txt; }; # 调用测试下 $dem ...
- 五:用JAVA写一个阿里云VPC Open API调用程序
用JAVA写一个阿里云VPC Open API调用程序 摘要:用JAVA拼出来Open API的URL 引言 VPC提供了丰富的API接口,让网络工程是可以通过API调用的方式管理网络资源.用程序和软 ...
- 一个实现单线程/多线程下代码调用链中传递数据的处理类: CallContext(LogicalSetData,LogicalGetData),含.net core的实现
详情请参考原文:一个实现单线程/多线程下代码调用链中传递数据的处理类: CallContext
- 依据ECMA规范,手写一个bind函数
Function.prototype.bind 函数,参见ECMA规范地址 如题,这次来实现一个boundFunction函数,不挂载在Function.prototype上,而是一个单独声明的函数. ...
- 写一个umi插件 自动生成代码 解放cv的双手
引言 最近在写一个中台项目,使用的react的umi框架. 各种增删改查.基本是列表页 新建页 详情页这种页面 为了避免不必要的简单重复(主要是想偷懒) 于是想去实现自己的一个代码生成器 探索 首先, ...
- 为LoadRunner写一个lr_save_float函数
LoadRunner中有lr_save_int() 和lr_save_string() 函数,但是没有保存浮点数到变量的lr_save_float函数.<lr_save_float() func ...
- JavaScript 自己写一个 replaceAll() 函数
JavaScript 的 replace() 方法可以在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串. 但是,只输入字符串的话,仅替换第一个字符,当然也可以用正则表达式来进行 ...
随机推荐
- leetcode每日一题:判断一个括号字符串是否有效
题目 一个括号字符串是只由 '(' 和 ')' 组成的 非空 字符串.如果一个字符串满足下面 任意 一个条件,那么它就是有效的: 字符串为 (). 它可以表示为 AB(A 与 B 连接),其中A 和 ...
- kubernetes学习之CKA认证
最近接触了很多kubernetes应用场景,学习了不少kubernetes的知识,所以想着官方认证一下CKA.不得不感叹:云时代真的来了. K8s的专业技术认证主要有以下几种: CKA(Kuberne ...
- Spring的AoP(面向切面编程)
作用: 就是把我们程序重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的 基础上,对我们的已有方法进行增强. 优势: 减少重复代码 提高开发效率 维护方便 AoP的实现方式:动态 ...
- 🎀杜伽Durgod K610W蓝牙连接问题解决
简介 杜伽Durgod K610W键盘支持三模连接,在配对成功蓝牙后切换连接通道后,再次连接蓝牙通道时无法正常自动连接已配对的蓝牙,需取消配对再重新配对后才能正常连接.这种问题可以通过升级键盘固件解决 ...
- python Response的语法
-- r.status_code #响应状态码 -- r.content #字节方式的响应体,会自动为你解码 gzip 和 deflate 压缩 -- r.headers #以字典对象存储服务器响应头 ...
- Sentinel源码—4.FlowSlot实现流控的原理
大纲 1.FlowSlot根据流控规则对请求进行限流 2.FlowSlot实现流控规则的快速失败效果的原理 3.FlowSlot实现流控规则中排队等待效果的原理 4.FlowSlot实现流控规则中Wa ...
- json导出csv
let data = [] let keys = ['name', 'town', 'village', 'address', 'update_time_label', 'manager'] let ...
- sonarqube+gitlab+jenkins+maven集成搭建(三)
安装JENKINS 关闭防火墙[root@localhost ~]# systemctl stop firewalld[root@localhost ~]# systemctl disable fir ...
- java处理http请求之Apache httpClient入门教程
说明 本文示例代码基于 4.5.13 版本 转载请注明出处:https://www.cnblogs.com/qnlcy/p/15378446.html 一.项目介绍 Apache 提供用来做http请 ...
- 定制Django的Tag和Filter(二)
配置 (1)最常见的放置自定义Tag和Filter的地方是在Django的app下.当一个app被添加到settings.py的INSTALLED_APPS 后,任何在它下面的合法位置将自动的可在te ...