C#调用C++动态库(dll)

在实际软件开发过程中,由于公司使用了多种语言开发,在C#中可能需要实现某个功能,而该功能可能用其他语言已经实现了,那么我们可以调用其他语言写好的模块吗?还有就是,由于C#开发好的项目,我们可以利用reflector等反编译工具反编译出其源代码,所以对于一些核心算法,我们不希望被别人知道,因此为了增强代码的安全性,我们需要将一些核心算法用C或C++来编写,然后用C#来调用这些已经写好的接口。在面对以上情况时,我们该怎么做呢?


方案一:重新实现
针对第一种情况,我们可以将C或者C++功能用C#来重新实现,这样的话代码比较统一,维护比较方便,但是这样的话增加了软件开发的成本,把C++的代码功能改成C#涉及到指针和内存的操作比较繁琐,况且有开发好的模块为什么不重复利用呢?针对第二种情况就不能得到有效解决,虽然可以使用混淆器对代码进行混淆,但是任然不是很安全。

方案二:封装COM组件
我们可以将C或者C++的函数封装成COM组件,在C#中调用时比较方便,但是COM组件需要注册,而且多次注册可能也会导致一些问题,同时在处理C或者C++的类型与COM组件的类型转换的时候也可能有些麻烦。


方案三:使用动态链接库
我们可以直接调用C或者C++已经写好的动态链接库,这样比较方便,这样很好的解决了上述问题。

在实际项目中,我们需要使用C#调用C++的一些接口,因此我使用的是方案三采用动态库,下面我就在实际中怎么处理的进行说明。
在调用动态库的过程中我也遇到了以下一些问题:
1、C++中有指针,C#中需要使用指针吗?
由于C++中的动态库中有指针参数,因此我也是用.NET的不安全代码,使用了C#的指针,但是最后也还是出现了一些问题,如在C#中传入的参数是一个二维数组时就出现了问题,这个问题我在网上找了好多资料也没有解决,最后和c++程序员商量了下改变了传入参数的参数类型。最后也没有使用指针。
2、C#和C++中的类型如何转换呢?
虽然C#和C++比较类似,但是其给我们的参数类型我们要与C#的参数类型一一对应起来,因此我找了一些资料把其类型一一对应了,具体看后续说明。
3、C++写好的动态库放到那个位置呢?
关于C++动态库的位置也是个问题,在应用中我们使用了相对路径和绝对路径进行测试,有的发现在VS中可以调用到,但是发布后发现无法调用到动态库,最后只要把动态的dll放到系统的目录system32下面才解决了改问题,目前还没找到其他的方法,如有其他的更好方法还请大家指点。
4、如何反编译C++的dll的名称,端口?
可以通过Dependency Walker工具进行反编译查看别人写的动态库的信息
5、还有其他的一些细节,如C#调用动态库需要指定其编码、代码写法等等

public class TestDLL
{
[DllImport(@"SomClient.dll", EntryPoint = "CreateSomClient", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern UInt32 CreateSomClient(String hostIp, UInt16 port);

[DllImport(@"SomClient.dll", EntryPoint = "ReleaseSomClient", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern void ReleaseSomClient(ref UInt32 clientHandle);
}

参数说明:

EntryPoint 指定要调用的 DLL 入口点。

CharSet 控制名称及函数中字符串参数的编码方式。默认值为 CharSet.Ansi。

ExactSpelling 是否修改入口点以对应不同的字符编码方式。

CallingConvention 指定用于传递方法参数的调用约定。默认值为 WinAPI。该值对应于基于32位Intel平台的 __stdcall。

BestFitMapping 是否启用最佳映射功能,默认为 true。最佳映射功能提供在没有匹配项时,自动提供匹配的字符

你可能感兴趣的:(C++)