VS2017编写纯C库以及使用C#调用C库方法

6 篇文章 1 订阅

若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/83825098
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究

红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门)

其他(编程相关)(点击传送门)

项目实战:Qt编译Qt库以及使用C#调用Qt库,并实现C#集成Qt的tcp客户端

VS2017编写MFC库以及使用Qt调用MFC库方法

VS2017编写纯C库以及使用C#调用C库方法

Qt实用技巧:VS2017编写纯C库以及使用Qt调用C库方法

关于 C#调用C库Dll,有回调函数时,只执行一次回调函数就直接挂掉 的解决方法

关于 C#调用一个C/C++dll库运行时实现多个应用(静态变量区分) 的解决方法

关于 C#调用c库,将C#的byte[]传入C库的方法和将C库的char*向上传入C#的回调函数byte[] 的方法

 

Demo源码下载

      https://download.csdn.net/download/qq21497936/10770528

 

建立C库

使用VS2017建立Visual C++ Dll空项目

打开VS2017建立Visual C++桌面向导,如下图:

点击确认后,开始向导创建工程,如下图:

点击“确认”,工程目录,如下图:

 

创建库源码,并生成C库

添加头文件(cDllDemo.h)与源文件(cDllDemo.cpp)

定义变量和函数宏定义

实现函数源码

编译生成动态库

添加回调函数

C库头文件添加(回调函数的全局变量指针和设置回调函数的函数)

C库源文件添加

解决被调用时可能无法查看到printf打印信息

 

winform以及wpf使用C库

创建wpf工程(winform工程调用也是一样)

设置依赖项,为了每次运行该测试应用之前,先编译生成对应的dll,方式dll修改未更新,如下图:

 

填入测试代码

运行时出现如下报错,调用不带输入参数的不报错,输入参数的签名对不上(就是函数定义);

此时我们修改c#调用方式,如下图:

运行结果:

使用C库中的全局变量

       在c中把全局变量的读写封装成函数,c#通过P/Invoke来调用函数(理解为set和get),修改c库头文件内容如下:

源文件如下:

       修改wpf程序如下:

运行结果如下:

使用C库中的回调函数

       首先,在C库头文件和源文件中定义回调函数全局变量和回调函数,如下图:

       在c#中回调步骤:1定义委托->2引入C库函数->3定义静态委托函数->4定义委托变量->5设置委托

在C#中若出现直接挂掉(当前项目中,若当机无异常或者无已停止运行,目前所知都是调用的C库挂掉的,从C库找原因),特别注意委托函数需要加上调用的方式,是Cdecl不是StdDecl,如下图:

       如果不写该项,则表示委托定义默认为StdDecl,读者可自行尝试,会跑完会后会直接挂掉,示意如下图:

理解[UnmanagedFunctionPointer(CallingConvention.Cdecl)]

  1. UnmanagedFunctionPointer:表示动态使用未托管的dll函数指针;
  2. CallingConvention.Cdecl:C调用约定(即用__cdecl关键字说明)按从右至左的顺序压参数入栈,由调用者把参数弹出栈。对于传送参数的内存栈是由调用者来维护的(正因为如此,实现可变参数的函数只能使用该调用约定)。另外,在函数名修饰约定方面也有所不同。_cdecl是C和C++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。VC将函数编译后会在函数名前面加上下划线前缀,是MFC缺省调用约定;
  3. CallingConvention.StdDecl:__stdcall调用约定相当于16位动态库中经常使用的PASCAL调用约定。在32位的VC++5.0中PASCAL调用约定不再被支持(实际上它已被定义为__stdcall。除了__pascal外,__fortran和__syscall也不被支持),取而代之的是__stdcall调用约定。两者实质上是一致的,即函数的参数自右向左通过栈传递,被调用的函数在返回前清理传送参数的内存栈但不同的是函数名的修饰部分(关于函数名的修饰部分在后面将详细说明)。_stdcall是Pascal程序的缺省调用方式,通常用于Win32Api中,函数采用从右到左的压栈方式,自己在退出时清空堆栈。VC将函数编译后会在函数名前面加上下划线前缀,在函数名后加上"@"和参数的字节数;

c库打印信息问题

C库添加打印语句

运行的代码

 

关闭应用后打印出来:

解决被调用时可能无法查看到printf打印信息

需要重定向输出,使用setbuf函数,如下图:

不能在运行时,每次调用,所以我们优化一下,定义一个初始化函数,修改库的头文件和源文件如下:

 

原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/83825098

  • 9
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长沙红胖子Qt(长沙创微智科)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值