经过大量的研究和实验,我仍然无法弄清楚从外部库访问非托管函数时遇到的问题。
快速相关的背景故事:我用 Visual C++ 编写了一个应用程序来驱动一个通过 USB 连接到系统的外部仪表,但正在虚拟化一个串行端口,我注意到奇怪的输出行为。为了为自己辩护,制造商希望我使用他们的 .dll 从我的应用程序中控制仪表。很好,但是....
我无法直接包含这个 .dll 作为参考(名称和路径已删除):
所以为了使用它,我大概查看了 DllImport。我决定将自己的程序集作为驱动程序的包装器,而不是将代码直接包含到我的应用程序中,这样我就可以通过类访问功能。在 .dll 上做了一个 dumpbin /exports 之后,我找到了所有函数的入口点,并像这样制作了一个 C# 类库,只包含相关示例:
namespace Meter
{
public class PortDrv
{
[DllImport("PortDrv.dll", EntryPoint = "SERIALNUMBER",
CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Auto)]
public static extern long SerialNumber(Byte Index);
[DllImport("PortDrv.dll", EntryPoint = "OPENPORT",
CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Auto)]
public static extern int OpenPort();
};
}
函数原型是从他们发给我的描述他们的库的 .pdf 文件中提取的:
SERIALNUMBER (ByVal Index As Byte) As Long
OPENPORT () As Integer
并且也在他们的示例 VB 程序中使用:
Private Declare Function SerialNumber Lib "PortDrv" Alias "SERIALNUMBER" (Index As Byte) As Long
Private Declare Function OpenPort Lib "PortDrv" Alias "OPENPORT" () As Integer
还在我这儿?行。所以在编译我自己的程序集之后,我添加了对我的应用程序的引用并访问了包装器:
int port_return = PortDrv::OpenPort();
Byte bite = 0x31;
__int64 serial = PortDrv::SerialNumber(bite);
但是在尝试检索序列号后它会爆炸:
而且我不太确定我哪里出错了。一些函数返回正确的信息,但似乎我必须传递信息才能失败。我已经尝试了 CharSets 和 CallingConventions 的所有不同组合,我已经将 ExactSpelling 设置为 true 等。有什么明显的地方我做错了,或者我可以不在我当前的环境中使用这个库吗?
编辑:我忘了提到,我将'1'传递给函数的原因是,如果只有一个仪表连接到系统,“索引”将为 1。如果有 2 个仪表,我可以访问第二个通过传入'2'。