我是一个C ++ DLL文件,一个lib
文件和一个头文件。我需要从我的C#应用程序中调用它们。
头文件如下所示:
class Clog ;
class EXPORT_MACRO NB_DPSM
{
private:
string sFileNameToAnalyze ;
Clog *pLog ;
void write2log(string text) ;
public:
NB_DPSM(void);
~NB_DPSM(void);
void setFileNameToAnalyze(string FileNameToAnalyze) ;
int WriteGenbenchData(string& message) ;
};
在我的C#代码中,我有这些代码:
internal ReturnStatus correctDataDLL(string rawDataFileName)
{
if (rawDataFileName == null || rawDataFileName.Length <= 0)
{
return ReturnStatus.Return_CannotFindFile;
}
else
{
setFileNameToAnalyze(rawDataFileName);
}
string msg = "";
int returnVal = WriteGenbenchData(ref msg);
return ReturnStatus.Return_Success;
}
[DllImport("..\\..\\thirdParty\\cogs\\NB_DPSM.dll")]
public static extern void setFileNameToAnalyze(string fileName);
[DllImport("..\\..\\thirdParty\\cogs\\NB_DPSM.dll")]
public static extern int WriteGenbenchData(ref string message);
我在EntryPointNotFoundException
声明中获得setFileNameToAnalyze(rawDataFileName);
。
几个问题:
我是否需要将lib
文件添加到我的C#项目的某个位置?怎么样?
我是否需要将头文件添加到我的C#项目中?怎么样? (暂时没有编译错误)
我想删除那些"..\\..\\thirdParty\\cogs\\"
硬编码路径。怎么样?
如何乘坐EntryPointNotFoundException
?
感谢,
答案 0 :(得分:2)
将函数放在任何类(作为全局函数)之外和extern "C" { ... }
块中。
您不需要C#中的头文件。 (这就是[DllImport]
所做的)
答案 1 :(得分:2)
您不需要在C#项目中包含头文件或lib文件。无论如何,这些文件对你来说都是无用的。
您获得EntryPointNotFound异常的原因是您为这些入口点提供了错误的名称。编译C ++项目时,编译器会通过添加有关参数和返回类型的其他信息来破坏名称。 (您可以使用dumpbin.exe实用程序查看这些入口点。)
然而,真正的问题是你的DLL显然包含一个C ++类。 “setFileNameToAnalyze”和“WriteGenbenchData”是该类的实例方法,而不是静态函数。如果不首先创建NB_DPSM类的实例,则无法调用它们。
可能只使用P / Invoke来做到这一点,但此时我认为它可能比它的价值更麻烦。您应该创建一个托管C ++类库来代替旧的DLL。
关于问题的第(3)部分,只需删除路径并确保NB_DPSM.dll与输出文件的结果位于同一bin目录中。
答案 2 :(得分:2)
可以尝试使用提供的dll将您自己的非托管C ++ dll作为填充程序 有1种方法
extern "C" int GenBenchData( const string &filename, string & message ){
NB_DPSM builder;
builder.setFileNameToAnalyze(filename);
return builder.WriteGenbenchData( message );
}
在C#中用
声明[DllImport("shim.dll", CharSet = CharSet.Auto)]
static extern int GenBenchData([MarshalAs(UnmanagedType.LPStr)]string filename, StringBuilder message);
答案 3 :(得分:1)
还要注意calling convention。如果您的DLL确实是C ++,请使用工具可视化导出的名称(如链接文章中提到的depends.exe)。每个C ++编译器都有自己的装饰方案,这使得它适应起来有点乏味。或者,您可以使用链接到C ++ DLL的包装器托管C ++程序集。如果它只是一个C接口,则需要考虑调用约定和类型大小(常见的陷阱:C#中的长整数是C / C ++中的64位,它是32位)