我有一个第三方C ++ .lib,我想在C#应用程序中使用。
我的目的是为.lib编写托管C ++包装器.dll,然后在我的C#应用程序中包含该包装器dll,使用大致类似the one outlined at this link的过程。
.lib的头文件不表示任何类声明或命名空间,只是方法名称:
int CheckNamedVariable(const char* _name);
int RegisterNamedVariable(const char* _name);
double GetNamedVariableValue(int _id);
double GetNamedVariableTypedValue(int _id, int _units);
void SetNamedVariableValue(int _id, double _value);
... (etc)
我用DUMPBIN / exports检查了lib,看看是否可以收集任何其他信息,并得到以下信息:
File Type: LIBRARY
Exports
ordinal name
?AircraftVarGet@@YANHHH@Z (double __cdecl AircraftVarGet(int,int,int))
?CheckNamedVariable@@YAHPBD@Z (int __cdecl CheckNamedVariable(char const *))
?DLLStart@@YGXXZ (void __stdcall DLLStart(void))
?DLLStop@@YGXXZ (void __stdcall DLLStop(void))
?GetAircraftVarEnum@@YAHPBD@Z (int __cdecl GetAircraftVarEnum(char const *))
?GetModuleVar@@YANW4GAUGE_TOKEN@@@Z (double __cdecl GetModuleVar(enum GAUGE_TOKEN))
?GetNameOfNamedVariable@@YAPBDH@Z (char const * __cdecl GetNameOfNamedVariable(int))
?GetNamedVariableTypedValue@@YANHH@Z (double __cdecl GetNamedVariableTypedValue(int,int))
?GetNamedVariableValue@@YANH@Z (double __cdecl GetNamedVariableValue(int))
?GetUnitsEnum@@YAHPBD@Z (int __cdecl GetUnitsEnum(char const *))
?IsPanelWindowVisibleIdent@@YAHI@Z (int __cdecl IsPanelWindowVisibleIdent(unsigned int))
?Panels@@3PAUPANELS@@A (struct PANELS * Panels)
?RegisterNamedVariable@@YAHPBD@Z (int __cdecl RegisterNamedVariable(char const *))
?SendKeyEvent@@YAXII@Z (void __cdecl SendKeyEvent(unsigned int,unsigned int))
?SetNamedVariableTypedValue@@YAXHNH@Z (void __cdecl SetNamedVariableTypedValue(int,double,int))
?SetNamedVariableValue@@YAXHN@Z (void __cdecl SetNamedVariableValue(int,double))
_ImportTable
_Linkage
Summary
ED .debug$S
14 .idata$2
14 .idata$3
4 .idata$4
4 .idata$5
1A .idata$6
在我的托管包装器项目中,我可以将链接器输入指向.lib,但我不确定如何调用lib中的方法(我链接的教程使用了命名空间和类)。如果它是C#/ VB项目中的普通旧DLL,我可以查看对象浏览器并了解如何调用库。
但鉴于我的C ++无知,我处于黑暗中。任何帮助表示赞赏。
修改 我尝试创建与标题中列出的方法同名的方法,例如:
int VariableExporter::IsPanelWindowVisibleIdent(unsigned int panel_id)
{
return IsPanelWindowVisibleIdent(panel_id);
}
这不是我希望的,它只是递归地调用自己(直到它有 - 等待它 - Stack Overflow)。
然后我尝试重命名包装器方法,如下所示:
int VariableExporter::IsPanelWindowVisibleIdent_New_Name(unsigned int panel_id)
{
return IsPanelWindowVisibleIdent(panel_id);
}
现在,虽然C ++ .DLL项目和C#项目都是编译的,但C#项目在尝试加载.DLL时会抛出一个FileNotFound异常。
答案 0 :(得分:1)
首先,要调用全局级别函数,您需要使用范围解析运算符::
int VariableExporter::IsPanelWindowVisibleIdent(unsigned int panel_id)
{
return ::IsPanelWindowVisibleIdent(panel_id);
}
没有必要(至少在这个简单的情况下)重命名你的方法。
其次,对于DLL-not-found问题,请检查C#应用程序的bin
路径中是否存在DLL。另外,检查wrapper-DLL本身是否可加载(使用Dependency Walker)。确保包装器DLL和C#应用程序的位相匹配。 64位应用程序无法加载32位DLL(反之亦然)。