龙空技术网

C#实战050:C#调用C++动态链接库及类库详解

编程手札 1987

前言:

此刻你们对“c语言扩展函数库”大概比较关注,你们都需要剖析一些“c语言扩展函数库”的相关资讯。那么小编同时在网络上网罗了一些对于“c语言扩展函数库””的相关文章,希望小伙伴们能喜欢,兄弟们一起来了解一下吧!

动态链接库

动态链接库全称Dynamic Link Library(简称DLL),通常是由一组实现某种特定功能的函数集合。它包含了该功能的具体实现方法和资源,通过编译生成一个后缀为DLL的文件供应用程序或者其他dll调用。用户不需要知道功能的具体实现过程,只需要根据DLL提供的API正确传参就可以得到想要的结果。

DLL的优点

DLL只有在被调用的时候才需要分配内存而且多个进程可以同时使用一个 DLL,在内存中共享该 DLL 的一个副本可以大大节省内存和减少交换操作。DLL可以使用多种编程语言编写,只要程序遵循函数的调用约定就可以被其他编程语言所调用,大大提高了代码复用性和拓展性。当DLL中的函数发生更改时只要函数的参数和返回值没有更改,就无需重新编译调用的应用程序,有助于应用程序的升级和优化等。

​C++编写DLL

在写Fanuc开发的时候我就喜欢把fanuc操作的所有功能编写成一个动态链接库,具体的实现方法可以参考专栏中的文章【C/C++实战023:动态类库的开发详解】。

这里要说的重点是该DLL在头文件中直接声明了成员方法,使用extern "C" __declspec(dllexport)标记将其直接导出。

​C#调用C++DLL

这类DLL在C#中采用[DLLImport(“DLL文件路径”)]特性标记方式来调用DLL中的函数 ,利用extern修饰符声明该DLL支持在外部实现的方法。这里需要注意参数的类型,声明之后就可以直接在C#编程中使用这个方法了。

[DllImport("FANUC_API.dll", SetLastError = true, EntryPoint = "Connect")]public static extern string Connect(byte[] ip, int port=8193, long timeout=2);
C++编写类库

类库就是实现各种功能方法的集合,当项目比较大的时候我们会把功能分的更细,这时候我们就会用到类库。将一些常用的编程任务(包括诸如字符串处理、数据格式转换、数据库连接以及文件访问等)封装成类库,方便在开发中直接使用类库封装的方法快速实现功能需求以提高开发效率!我在NX二次开发的时候就会把具体的功能进行类库封装,里面包含了该功能实现所以的成员方法和成员属性。

​C#调用C++类库

这里需要注意的是C#属于托管型代码而C++是非托管型代码,托管型代码的对象在托管堆上分配内存而非托管型代码对象有实际的内存地址,所以C#不能直接调用C++类库中的类。要实现C#调用C++类库要么将C++类库改成托管型C++dll库,要么就通过另一个C++动态链接库将要调用的类成员方法导出。

​托管型C++类库

修改之前写好的类库,在编写动态链接库时通过项目属性->高级->公共语言运行时支持,将默认“无公共语言运行时支持”改成“公共语言运行时支持(/clr)”。此时我们新建一个C#的控制台程序来测试,引用刚生成的DLL文件(默认无公共语言运行时支持的DLL无法被C#引用)并在Main函数中实例化该类。

​C++定义托管类

这时你会发现代码提示:“EDIT”不可访问,因为它具有一定的保护级别,这时我们需要为动态链接库中的class类添加public将其设置为公有类,允许通过类的实例变量进行访问。并利用ref创建托管类对象,这时候就不能再用extern "C" __declspec(dllexport)标记将导出了(该方式不适用于托管类型) ,这里我们设定编译器的状态指令为#pragma once(保证头文件被编译一次)。#pragma指令在保持与C和C++语言完全兼容的情况下,为编译器提供主机或操作系统专有的特征。

C#调用C++类库

​这时候我们在C#控制台中就可以通过实例化该类来调用其成员方法,这里我们可以发现原函数中的char*类型参数在C#调用后提示参数类型为sbyte*类型。这是因为C++和C#之间使用不同数据类型,所以当C#调用C++编写的类库时就需要转换数据类型。不过C++的char*对应C#不应该是byte[]么,怎么变成sbyte*了(第一次见)?为了传参我需要将string类型先转成sbyte[]类型,再通过fixed将sbyte[]类型转成sbyte*类型。这说明该方法引用的类存在不安全隐患,容易导致内存泄露。

非托管型C++类库

还有一种方式就是创建一个新的C++动态链接库,这个动态链接库专门用来调用类库中的成员方法并将其导出。在方法中实例化类通过公共方法间接调用类成员方法并将其暴露出去,这样C#就可以直接通过[DLLImport(“DLL文件路径”)]特性标记方式来调用DLL中的函数了。

总结:

从上面的调用来看C++定义托管型类库会存在安全隐患而且还不适应其他语言调用,所以还是建议用标准的C++库。利用一个导出库将所有类库中的成员方法暴露出去,像UG等大型大软件都是这样来操作的。以上内容是小编给大家分享的【C#实战050:C#调用C++动态链接库及类库详解】,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。

标签: #c语言扩展函数库 #c调用dll库函数