经过大量的研究和实验,我仍然无法弄清楚我从外部库中访问未管理的函数时遇到的问题。
快速相关的背景故事:我用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'可以访问第二个。答案 0 :(得分:5)
您提供的示例VB程序:
Private Declare Function SerialNumber Lib "PortDrv" Alias "SERIALNUMBER" (Index As Byte) As Long
不说ByVal
。 VB中的默认值为ByRef
。这是你的错字还是问题?如果是这样,您需要在签名中将ref Byte
说成SerialNumber。
道德:总是说ByRef
或ByVal
。