从C#调用C ++ dll中的方法没有任何信息,只有头文件

时间:2016-11-10 08:48:24

标签: c# c++ pinvoke dllimport

我有一个第三方DLL,我试图在C#中编写一个包装器并且有C ++示例代码,但是当我尝试调用DLL中的方法时,我得到错误:

无法找到名为' scan'的入口点在DLL' scard-com.dll'。

请帮助指出我的问题:

以下是示例C ++应用程序中使用的.h文件的一部分

interface ISCard_CardReaderDevices : IUnknown {
virtual UINT __stdcall scan(void) = 0;
virtual UINT __stdcall getDeviceCount(void) = 0;
virtual const CHAR * __stdcall getDeviceName(UINT id) = 0;
virtual const CHAR * __stdcall getSerialName(UINT id) = 0;
virtual ISCard_CardReader * __stdcall connectById(UINT id) = 0;
virtual ISCard_CardReader * __stdcall connectByName(const CHAR *name) = 0;
virtual ISCard_CardReader * __stdcall connectBySerial(const CHAR *serial) = 0;
virtual BOOL __stdcall disconnect(ISCard_CardReader *reader) = 0;
virtual ISCard_SecMsg * __stdcall attachSecMsg(ISCard_CardReader *reader) = 0;
virtual void __stdcall detachSecMsg(ISCard_SecMsg *secMsg) = 0;
virtual ISCard_Script * __stdcall attachScript(ISCard_CardReader *reader) = 0;
virtual void __stdcall detachScript(ISCard_Script *script) = 0;
virtual ISCard_IsoCard * __stdcall attachIsoCardByReader(ISCard_CardReader *reader) = 0;
virtual ISCard_IsoCard * __stdcall attachIsoCardBySecMSG(ISCard_SecMsg *secMsg) = 0;
virtual void __stdcall detachIsoCard(ISCard_IsoCard *isocard) = 0;
virtual ISCard_MTCOS * __stdcall attachMTCOSByReader(ISCard_CardReader *reader) = 0;
virtual ISCard_MTCOS * __stdcall attachMTCOSBySecMSG(ISCard_SecMsg *secMsg) = 0;
virtual void __stdcall detachMTCOS(ISCard_MTCOS *os) = 0;
virtual ISCard_IcaoConverter * __stdcall attachIcaoConverter(void) = 0;
virtual void __stdcall detachIcaoConverter(ISCard_IcaoConverter *icaoconv) = 0;
virtual ISCard_ImageConverter * __stdcall attachImageConverter(void) = 0;
virtual void __stdcall detachImageConverter(ISCard_ImageConverter *imgconv) = 0;
#ifdef MULTIAPP_EXT
virtual ISCard_IDLConverter * __stdcall attachIDLConverter(void) = 0;
virtual void __stdcall detachIDLConverter(ISCard_IDLConverter *idlconv) = 0;
virtual ISCard_sscdConverter * __stdcall attachSSCDConverter(void) = 0;
virtual void __stdcall detachSSCDConverter(ISCard_sscdConverter *sscdconv) = 0;
virtual ISCard_eHealthConverter * __stdcall attacheHealthConverter(void) = 0;
virtual void __stdcall detacheHealthConverter(ISCard_eHealthConverter *eHealthconv) = 0;
#endif // MULTIAPP_EXT
};

在我的C#项目中,我添加了这个类:

public class SCardWrapper
{
    [DllImport("scard-com.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern uint scan();

// And call it like this:

public int listReaders()
    {
        try
        {
            uint numreaders = scan();
            if (numreaders < 1)
            {
                return 0;
            }
            for (int i = 0; i < numreaders; i++)
            {
                IntPtr iDevice = getDeviceName(uint.Parse(i.ToString()));
                String sDevice = Marshal.PtrToStringAuto(iDevice);
                Debug.WriteLine(string.Format("{0} : " + sDevice, i));
            }
            return int.Parse(numreaders.ToString());
        }
        catch
        {
            return -1;
        }
    }
}

但是一旦它遇到scan()方法,我就会得到上面的错误。任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:1)

P / Invoke 确实不支持C ++。你试图在一个接口上调用一个方法,而不是一个C风格的函数。

有些hacks可以为您提供所需的结果,但通常到目前为止最好的选择是编写可以在C#项目中使用的C ++ / CLI互操作库。

此外,通常,头文件不足以正确调用本机库。你需要这些文档 - 还有一些问题可以解决诸如“字符串缓冲区应该有多大的问题?谁负责分配/释放内存?当缓冲区不够大时会发生什么?有什么可能?”错误条件?“如果您没有这些文档,那么除了享受逆向工程外,您几乎无法做到:)

答案 1 :(得分:0)

此类scan声明:

public class SCardWrapper
{
    [DllImport("scard-com.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern uint scan();
}

是来自DLL scan的名为scard-com.dll的函数的绑定。在scard-com.dll DLL接口中检查此功能。为此,您可以使用Dependency Walker

您的DLL中的

scan名称可以是mangled。在这种情况下,您可以在非托管代码中将其定义为extern "C",或者将EntryPoint = "mangled_scan_name"添加到您的PInvoke声明中。

顺便说一下,scan不属于上面interface ISCard_CardReader的一部分。但如果它是一个类的方法,那么CallingConvention = CallingConvention.Cdecl是不正确的。