C#调用C ++ dll获取EntryPointNotFoundException

时间:2010-06-15 21:06:43

标签: c# .net

我是一个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);

几个问题:

  1. 我是否需要将lib文件添加到我的C#项目的某个位置?怎么样?

  2. 我是否需要将头文件添加到我的C#项目中?怎么样? (暂时没有编译错误)

  3. 我想删除那些"..\\..\\thirdParty\\cogs\\"硬编码路径。怎么样?

  4. 如何乘坐EntryPointNotFoundException

  5. 感谢,

4 个答案:

答案 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位)