4

经过大量的研究和实验,我仍然无法弄清楚从外部库访问非托管函数时遇到的问题。

快速相关的背景故事:我用 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'。

4

1 回答 1

5

您提供的示例 VB 程序:

Private Declare Function SerialNumber Lib "PortDrv" Alias "SERIALNUMBER" (Index As Byte) As Long  

不说ByVal。VB 中的默认值是ByRef. 这是您的错字还是问题所在?如果是这样,您需要ref Byte在签名中注明 SerialNumber。

道德:总是说ByRefByVal

于 2012-05-04T12:28:35.103 回答