从c#调用c++ dll中的方法,没有任何信息,只有头文件
本文关键字:任何 文件 信息 方法 调用 c++ dll | 更新日期: 2023-09-27 18:17:10
我有一个第三方DLL,我试图在c#中编写包装器,并有c++示例代码,这是有效的,但当我尝试调用DLL中的方法时,我得到错误:
无法在DLL ' card-com. DLL '中找到名为'scan'的入口点。
请帮忙指出我的问题:
下面是示例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()方法,我就会得到上面的错误。任何帮助将不胜感激!
p/Invoke并不真正支持c++。你正在尝试调用接口上的方法,而不是c风格的函数。
有一些技巧可以让你得到你想要的结果,但通常到目前为止,最好的选择是编写一个c++/CLI互操作库,你可以在你的c#项目中使用。
而且,一般来说,头文件不足以正确调用本机库。您需要文档-有noöne握住您的手在诸如"字符串缓冲区应该有多大?"谁负责分配/释放内存?当缓冲区不够大时会发生什么?可能的错误条件是什么?"如果你没有文档,除了享受逆向工程,你几乎没有什么可以做的:)
scan
声明:
public class SCardWrapper
{
[DllImport("scard-com.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern uint scan();
}
是DLL scard-com.dll
中名称为scan
的函数的绑定。检查此功能在您的scard-com.dll
DLL接口。你可以使用Dependency Walker。
scan
名称可以在DLL中修改。在这种情况下,您可以在非托管代码中将其定义为extern "C"
,或者将EntryPoint = "mangled_scan_name"
添加到PInvoke声明中。
scan
不是上面interface ISCard_CardReader
的一部分。但是如果它是一个类的方法,那么CallingConvention = CallingConvention.Cdecl
是不正确的