从C#调用C ++ DLL方法/类

时间:2015-04-21 22:38:35

标签: c# visual-c++ dll pinvoke

我编写了一些软件来自动化某些第三方软件,并发现有必要调查该软件自己的dll。


注意:不幸的是,我有权访问源代码或开发人员


使用PInvoke很容易调用dll的静态方法,但据我所知,没有C ++ / CLI包装器就无法实例化类。

答案似乎是围绕dll创建一个C ++ / CLR包装器,如this answer中所示。 虽然显然是一个很好的答案,但我以前从未创建过C ++应用程序,也不知道完全该做什么。

我已经使用了依赖walker来获取我想要使用的函数名:sdk_string::sdk_string(const char *)(如装饰:??0sdk_string@@QAE@XZ)。在那个入口点尝试PInvoke只会以悲伤和自怜结束。

从我收集的内容来看,我需要:

  1. 创建一个新的Visual C ++ CLR类库。
  2. 在主.h头文件中写下如下内容:sdk_string* CreateSdkString(const char * chars) { return new sdk_string(chars); }
  3. 以某种方式调用new sdk_string(chars)来调用第三方dll?
  4. ?????? (我是否需要以任何特殊方式构建它,以便我可以轻松地启用我的CreateSdkString功能?)
  5. Upvote并接受您的回答。 : - )
  6. 我认为上面的第3步是我的问题:如何调用new sdk_string(chars)来调用第3方dll?但如果我对其他事情不对,那么那些其他我错的是我的问题。

    更新

    仅供参考,以下是此类的整个Dependency Walker函数名称输出:

    const sdk_string ::`vftable'
    class sdk_string& sdk_string :: append(class sdk_string const&)
    class sdk_string& sdk_string ::追加(焦炭)
    class sdk_string& sdk_string :: append(char *)
    class sdk_string& sdk_string :: append(char const *)
    char const * sdk_string :: c_str(void)
    bool sdk_string :: contains(char const *)
    bool sdk_string :: empty(void)
    bool sdk_string :: endsWith(char const *)
    int sdk_string :: equals(class sdk_string const&)
    int sdk_string :: equals(char const *)
    int sdk_string :: equalsIgnoreCase(class sdk_string const&)
    int sdk_string :: equalsIgnoreCase(char const *)
    void sdk_string :: erase(int,int)
    bool sdk_string :: hasAlphaChars(void)
    int sdk_string :: indexOf(class sdk_string const&)
    int sdk_string :: indexOf(char)
    int sdk_string :: indexOf(char,int)
    int sdk_string :: indexOf(char const *)
    void sdk_string :: insert(int,char const *)
    bool sdk_string :: isAllDigits(void)
    bool sdk_string :: isAllWhiteSpace(void)
    int sdk_string :: length(void)
    class sdk_string& sdk_string :: operator =(class sdk_string const&)
    class sdk_string& sdk_string :: operator =(char *)
    void sdk_string :: replace(int,int,class sdk_string const&)
    void sdk_string :: replace(char const *)
    sdk_string :: sdk_string(wchar_t *&)
    sdk_string :: sdk_string(class sdk_string const&)
    sdk_string :: sdk_string(char const *)
    sdk_string :: sdk_string(无效)
    void sdk_string :: setData(char const *)
    bool sdk_string :: startsWith(char const *)
    bool sdk_string :: stretch(int)
    void sdk_string :: stripLeadingSpaces(void)
    void sdk_string :: stripSpaces(void)
    void sdk_string :: stripTrailingSpaces(void)
    void sdk_string :: substr(int,int,class sdk_string&)
    void sdk_string :: toUpper(class sdk_string&)
    sdk_string ::〜sdk_string(void)

2 个答案:

答案 0 :(得分:1)

  

我想我错过了一些非常明显的难题......如何从第三方.dll中获取函数/类到我的新C ++ / CLR包装中,以便我可以调用它

使用非托管库提供的头文件和导入库,就像将任何DLL导入非托管项目一样。在任何引用库的源文件中包含头文件,并将导入库传递给链接器。

但是,在DLL中实现的已发布的基于C ++类的接口令人惊讶。它对编译器的选择有严格的限制。我怀疑你是对一个私有库进行逆向工程,因此不会有头文件或导入库。对它们进行逆向工程可能是一个难以追究的问题。我建议联系图书馆的开发者寻求支持。

答案 1 :(得分:0)

显然你只需要一些方法/功能,所以在这种情况下你能做的最好就是创建头文件(你的选项2)。如果你需要更多(很多)类/方法,你可以检查http://www.swig.org/它可以创建C#的包装器,但它需要定义,例如,你可以创建一个头文件,让我们把它命名为myHeader.h,像这样:

class A
{
public:
int intMethod(float param);
}

如果您创建了一个文件,请使用以下内容将其命名为myHeader.i:

%module myHeader_wrapper
%{
//Here could be the header file or directly the class/functions definition
    #include "myHeader.h"
%}
%include "myHeader.h"

之后你运行:

swig -csharp myHeader.i

应创建名为myHeader_wrap.c和myHeader.cs的文件。使用.c文件创建C ++ DLL并使用C#项目中的.cs文件来访问类。当然,可以使用IDE工具自动化swig事物(例如,使Visual Studio运行后构建操作)。