PInvoke和EntryPointNotFoundException

时间:2011-05-04 00:53:04

标签: c# .net pinvoke

我无法理解下面的pinvoke有什么问题导致了EntryPointNotFoundException:

C中带有结构声明的函数:

    extern "C"__declspec (dllimport) __stdcall
    LONG NET_DVR_Login_V30 (char *sDVRIP,  WORD wDVRPort,  char *sUserName,
                        char *sPassword,  LPNET_DVR_DEVICEINFO_V30 lpDeviceInfo);

    typedef struct
    {
        BYTE sSerialNumber[48]; 
        BYTE byAlarmInPortNum;
        BYTE byAlarmOutPortNum;
        BYTE byDiskNum;
        BYTE byDVRType;
        BYTE byChanNum;
        BYTE byStartChan;
        BYTE byAudioChanNum;
        BYTE byIPChanNum;
        BYTE byZeroChanNum;
        BYTE byMainProto;
        BYTE bySubProto;
        BYTE bySupport;
        BYTE byRes1[20];
    }NET_DVR_DEVICEINFO_V30,  *LPNET_DVR_DEVICEINFO_V30; 

C#中的导入,结构声明和pinvoke:

    [DllImport("SDK.dll", SetLastError = true,
        CallingConvention = CallingConvention.StdCall)]
        public extern static int NET_DVR_Login_V30(
            [MarshalAs(UnmanagedType.LPStr)] string sDVRIP,
            ushort wDVRPort,
            [MarshalAs(UnmanagedType.LPStr)] string sUserName,
            [MarshalAs(UnmanagedType.LPStr)] string sPassword,
            ref NET_DVR_DEVICEINFO_V30 lpDeviceInfo);

    [StructLayout(LayoutKind.Sequential,
        CharSet = CharSet.Ansi)]
        public struct NET_DVR_DEVICEINFO_V30
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 48)]
            public string sSerialNumber;
            public byte byAlarmOutPortNum;
            public byte byDiskNum;
            public byte byDVRType;
            public byte byChanNum;
            public byte byStartChan;
            public byte byAudioChanNum;
            public byte byIPChanNum;
            public byte byZeroChanNum;
            public byte byMainProto;
            public byte bySubProto;
            public byte bySupport;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
            public string byRes1;
        }

           NET_DVR_DEVICEINFO_V30 deviceInfo = new NET_DVR_DEVICEINFO_V30();
           int result = Functions.NET_DVR_Login_V30(ip, port, user,
                                                 password, ref deviceInfo);

我通过dumpbin检查了函数名称,并没有损坏它。所以我想知道为什么会发生EntryPointNotFoundException,如果参数有任何问题,例如,会发生PInvokeStackImbalance错误,比方说。 任何想法这个pinvoke可能有什么问题?

2 个答案:

答案 0 :(得分:1)

有一个名为Dependency Walker(depends.exe)的工具可以通过显示SDK.DLL的导入/导出表来帮助调试此问题 - 我会看一下。另一件事可能(这似乎让我怀疑)正在发生的事情是,因为你正在使用char *,.NET在你的函数名的末尾添加了一个“A”。那可能是balderdash。

答案 1 :(得分:0)

显然,名称不匹配。因此,您需要确保界面的两侧使用相同的名称:

  • 当从DLL导出函数作为stdcall时,它将被装饰。您可以使用.def文件来避免此装饰。
  • 使用P / Invoke导入时,您需要禁止添加WA后缀。通过将DllImportAttribute的{​​{3}}字段设置为true
  • 来执行此操作