在大型项目开发中,往往要使用强大的第三方库,比如说中间件使用基于c++开发的OpenDDS,但是项目逻辑层可能用的是其他语言,比如c#,所以基于这样的情况,不同编程语言之间的相互调动问题是逃避不了的。
举一个在windows平台,IDE在vs2015,c#调用c++的例子。
1、创建一个c++动态库项目
这个就不展开说了,网上的资料很多,不再叙述。
创建完成如图:
2、生成基于c++的dll文件
应用程序如果想要访问某个DLL中的函数,那么该函数必须是已经被导出来的函数。
现在我们打开CSharpInvoke.cpp,添加如下代码:
_declspec(dllexport) int add (int a, int b)
{
return a + b;
}
_declspec(dllexport) int subtract (int a, int b)
{
return a - b;
}
为了让DLL导出函数,需要在每一个将要被导出的函数前面添加标识符:_declspec(dllexport)
编译生成文件,如图:
那么如何查看该DLL的函数已经被导出来了呢?我们使用vs自带的工具dumpbin。
在vs的安装文件中搜索”dumpbin.exe”,并为之设置为系统环境变量,这样我们就可以在任何文件下使用dumpbin命令了。
运行如下图:
可以看出来,我们的add和subtract是被导出来了,但是函数名前后多出了很多字符,这是因为c++编译器为了支持重载,所以在编译的时候给每一个接口都重新定义了唯一的名字,这个过程被称为“名字粉碎”。这个名字就是dll找到接口的入口地址。
4、c#应用程序调用dll
创建一个名叫start_cs的C#控制台程序。
填入如下代码:
public class CPPDLL
{
[DllImport("use_c++.dll",EntryPoint = "?add@@YAHHH@Z")]
public static extern int add(int x, int y);
[DllImport("use_c++.dll", EntryPoint = "?subtract@@YAHHH@Z")]
public static extern int subtract(int x, int y);
}
class Program
{
static void Main(string[] args)
{
int result = CPPDLL.add(10,20);
Console.WriteLine("10 + 20 = {0}", result);
Console.ReadLine();
}
}
注意:EntryPoint后面跟着的是c++编辑器可以识别的函数入口,如果运行例子出现类似“……找不到程序入口”多半是没告诉编辑器能识别的接口名。
运行:
成功。
第一步简单的例子,我们是运行成功了的,而c++中存在的指针、或者我们需要调用c++对象中的一个接口,更深层次的关于调用问题,比如类型对照问题,内存释放问题等后续会继续更新。