简体   繁体   English

C#调用C ++ dll获取EntryPointNotFoundException

[英]C# call a C++ dll get EntryPointNotFoundException

I was gaven a C++ dll file, a lib file and a header file. 我是一个C ++ DLL文件,一个lib文件和一个头文件。 I need to call them from my C# application. 我需要从我的C#应用​​程序中调用它们。

header file looks like this: 头文件看起来像这样:

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) ;
};

In my C# code, I have those code: 在我的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);

I got EntryPointNotFoundException at the setFileNameToAnalyze(rawDataFileName); 我在setFileNameToAnalyze(rawDataFileName);得到了EntryPointNotFoundException setFileNameToAnalyze(rawDataFileName); statement. 声明。

Few questions: 几个问题:

  1. do I need to add that lib file into somewhere of my C# project? 我需要将该lib文件添加到我的C#项目的某个地方吗? how? 怎么样?

  2. do I need to add the header file into my C# project? 我需要将头文件添加到我的C#项目中吗? how? 怎么样? (no compile error for now) (现在没有编译错误)

  3. I would like to remove those "..\\\\..\\\\thirdParty\\\\cogs\\\\" hardcode path. 我想删除那些"..\\\\..\\\\thirdParty\\\\cogs\\\\"硬编码路径。 how to this? 怎么样?

  4. how to get ride of that EntryPointNotFoundException ? 如何获得EntryPointNotFoundException

thanks, 谢谢,

Place the functions outside any classes (as global functions) and in an extern "C" { ... } block. 将函数放在任何类(作为全局函数)之外和extern "C" { ... }块中。

You don't need the header file in C#. 您不需要C#中的头文件。 (That's what the [DllImport] does) (这就是[DllImport]作用)

You don't need to include either the header file or the lib file in your C# project. 您不需要在C#项目中包含头文件或lib文件。 These files are useless to you anyway. 无论如何,这些文件对你来说都是无用的。

The reason you are getting an EntryPointNotFound exception is that you've provided incorrect names for those entry points. 您获得EntryPointNotFound异常的原因是您为这些入口点提供了错误的名称。 When you compile a C++ project, the compiler mangles the names by adding additional information about parameters and return types. 编译C ++项目时,编译器会通过添加有关参数和返回类型的其他信息来破坏名称。 (You can use the dumpbin.exe utility to see these entry points.) (您可以使用dumpbin.exe实用程序查看这些入口点。)

The real problem, however, is that your DLL evidentally contains a C++ class. 然而,真正的问题是你的DLL显然包含一个C ++类。 "setFileNameToAnalyze" and "WriteGenbenchData" are instance methods of that class, not static functions. “setFileNameToAnalyze”和“WriteGenbenchData”是该类的实例方法,而不是静态函数。 You can't call them without creating an instance of the NB_DPSM class first. 如果不首先创建NB_DPSM类的实例,则无法调用它们。

It might be possible to do that using only P/Invoke, but at this point I think it's likely more trouble than it's worth. 可能只使用P / Invoke来做到这一点,但此时我认为它可能比它的价值更麻烦。 You should create a managed C++ class library to wrap the old DLL instead. 您应该创建一个托管C ++类库来包装旧的DLL。

As to part (3) of your question, just remove the paths and make sure that NB_DPSM.dll resides in the same bin directory as the result of your output files. 至于问题的第(3)部分,只需删除路径并确保NB_DPSM.dll与输出文件的结果位于同一个bin目录中。

Could try make your own unmanaged C++ dll as a shim, using the provided dll have 1 method 可以尝试将自己的非托管C ++ DLL作为垫片,使用提供的dll有1个方法

extern "C" int GenBenchData( const string &filename, string & message ){
  NB_DPSM builder;
  builder.setFileNameToAnalyze(filename);
  return builder.WriteGenbenchData( message );
}

in C# you declare that with 在C#中你声明了

[DllImport("shim.dll", CharSet = CharSet.Auto)]
static extern int GenBenchData([MarshalAs(UnmanagedType.LPStr)]string filename, StringBuilder message);

Also beware of the calling convention . 还要注意调用约定 If your DLL is really C++, use a tool to visualize the exported names (like depends.exe referred in the linked article). 如果您的DLL确实是C ++,请使用工具可视化导出的名称(如链接文章中提到的depends.exe)。 Each C++ compiler has its own decoration scheme what makes it a bit tedious to adapt. 每个C ++编译器都有自己的装饰方案,这使得它适应起来有点乏味。 Alternatively you can use a wrapper managed C++ assembly that links to the C++ DLL. 或者,您可以使用链接到C ++ DLL的包装器托管C ++程序集。 If it is just a C interface take care of the calling convention and the type sizes (common pitfall: a long in C# is 64bit in C/C++ it is 32bit) 如果它只是一个C接口,则需要考虑调用约定和类型大小(常见的陷阱:C#中的long长度为64位,C / C ++为32位)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM