在c#中调用c dll
Calling c dll in C#
问题简介:
我必须通过API来控制某个设备,该API提供了一个DLL文件、LIB文件和c头文件,这些文件的函数被声明为dllimport。
当我在C++项目中使用API时,一切都很好——我包含了头、lib、dll,并调用了头文件中声明的函数。
当试图使用[DllImport]属性从C#.NET项目调用这些函数时,问题就开始了:这些函数是用确切的名称和参数声明的,运行代码没有引发任何异常。然而,该设备根本没有响应,就像从未真正调用过这些函数一样。
如何在C标头中声明:
int __declspec(dllimport) Init_Card_RTx(unsigned short device_num, unsigned short enabled_channels, unsigned short xmt_channels);
如何在C#中声明:
[DllImport(Path, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Init_Card_RTx")]
public static extern int Init_Card_RTx(UInt16 device_num, UInt16 enabled_channels, UInt16 xmt_channels);
问题:
- 这是因为标头中的函数被声明为dllimport吗
- 在这种情况下,我是否必须用声明为dllexport的C++函数包装DLL
- 从C#访问C DLL需要哪些步骤
- 在C#项目中,我是否也必须包含LIB文件?不仅仅是DLL文件本身
这是因为标头中的函数被声明为dllimport吗?
可能。需要导出函数。它们是否被导出取决于它们的DLL是如何由提供给你的人编译的。我想它们应该是(或者C++代码会尝试导入它们并失败)
排除此类故障时,我要做的第一件事是在Dependency Walker中加载DLL,它将向您显示所有导出的函数。如果它们没有出现,它们就不会被导出,C#也不能调用它们。如果它们出现了,那么您就可以了,不需要更改任何C代码或创建任何包装函数。
在这种情况下,我是否必须用声明为dllexport的C++函数包装DLL?
否。C#只能使用DllImport调用C函数。C++在导出函数时会进行名称篡改,这会使事情变得一团糟,而且通常不可行。
您需要做的是以某种方式导出您的函数。我的猜测是,它们已经导出了,但如果没有,您可以制作一些这样的包装器函数。
int __declspec(dllexport) Init_Card_RTx(unsigned short device_num, unsigned short enabled_channels, unsigned short xmt_channels) {
// just call the other function here
}
这些应该会使函数导出,并且您应该看到它显示在依赖项walker中。
从C#访问C DLL需要哪些步骤?
CLR必须能够找到dll(通常只需将其与C#exe放在同一目录中),并且函数必须导出为C函数。差不多了。
在C#项目中,我是否也必须包含LIB文件?不仅仅是DLL文件本身?
您根本不需要在C#项目中包含任何内容,只需要包含带有DllImport
属性的public static extern
包装函数即可。只要CLR能够在运行时找到dll,这就是您所需要的。如果它在运行时找不到它,那么在调用第一个导入的方法时应该会得到一个异常。
附言:获取依赖助行器。对于这种东西,我再怎么推荐它也不为过了
这种事情总是让人头疼。您必须确保传递的数据的字节结构与DLL所期望的一致,并且准确无误。C#中的本机结构不知道它们是从外部传递的,所以必须更严格地构造代码。
请参阅此处了解更多信息:
http://msdn.microsoft.com/en-us/library/awbckfbz(v=vs.110).aspx
函数被声明为dllimport
的原因是(如果我错了,请纠正我)DLL是由您的卡供应商提供的,这没关系,因为只有在构建DLL时才需要dllexport
[DllImport(Path, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Init_Card_RTx")]
第一个论点Path
只是为了说明问题,对吗?
你能用dependens.exe或PE资源管理器打开DLL吗(http://www.heaventools.com/download-pe-explorer.htm)并查看DLL的导出表?
我之所以这么问,是因为函数名可能被修饰了,如果DLL被编译为C++而不是普通的C.,就会发生这种情况
试着这样解密(在CPP文件中只做一次,而不是头文件)
extern "C" __declspec(dllexport) int __stdcall Init_Card_RTx(unsigned short device_num, unsigned short enabled_channels, unsigned short xmt_channels)
{
//
}
在C#中:
[DllImport("MyDll.dll")]
int Init_Card_RTx(ushort device_num, ushort enabled_channels, ushort xmt_channels);
您需要导出它并用extern"C"声明__stdcall很方便,因为它是.net端的默认值。我在C++项目中有一个宏,以确保每次都键入相同的宏。
是的,依赖行者。。。。
- 如何安全地从 DLL 调用返回对象
- C++结构到德尔福记录dll调用
- 从 C#-DLL 调用函数的 C++ 失败
- 可视C++:XGBoost 从 DLL 调用时不起作用
- Unity3D的OpenCV dll调用导致FPS下降
- 创建一个C++DLL以从C#DLL调用方法
- 从 dll 调用 opencv 垫到 Windows 表单,图像出现故障
- 努力使用 C# 从本机 DLL 调用该方法
- WinAPI - GetLastError 在通过 COM ATL DLL 调用时始终返回 0
- 必须使用C DLL调用C#.NET方法
- 如何直接从 pdfium.dll 调用 v8 函数
- 为什么从 DLL 调用类方法需要虚拟说明符?
- VBA 中的多个 DLL 调用
- 挂钩VirtualAlloc在系统DLL调用时返回NULLPTR
- 无法从 C DLL 调用该函数
- DLL 调用涉及 strncpy() 的方法
- JNA从DLL调用C++对象-java.lang.IollegalArgumentException:Structure
- 德尔福动态DLL调用中的奇怪行为
- 从非托管 DLL 调用 UWP api
- boost::从 DLL 调用时日志格式不起作用