【发布时间】:2015-06-29 08:03:00
【问题描述】:
我编写了一些软件来自动化一些第 3 方软件,并发现有必要考虑调用该软件自己的 dll。
注意:很遗憾,我无权访问源代码或开发者
使用 PInvoke 调用 dll 的静态方法很容易,但据我所知,如果没有 C++/CLI 包装器,就无法实例化类。
答案似乎是围绕 dll 创建一个 C++/CLR 包装器,如 this answer 中所示。 虽然显然是一个很好的答案,但我以前从未创建过 C++ 应用程序,也不知道确切该做什么。
我已经使用dependency walker 来获取我想使用的函数名:sdk_string::sdk_string(const char *)(装饰:??0sdk_string@@QAE@XZ)。在那个入口点尝试 PInvoke 只会以悲伤和自怜而告终。
根据我收集到的信息,我需要:
- 新建一个 Visual C++ CLR 类库。
- 在主 .h 头文件中写入如下内容:
sdk_string* CreateSdkString(const char * chars) { return new sdk_string(chars); } - 以某种方式让
new sdk_string(chars)调用调用第三方 dll? - ?????? (我是否需要以任何特殊方式构建它,以便轻松 PInvoke 我的
CreateSdkString函数?) - 支持并接受您的回答。 :-)
我认为上面的第 3 步是我的问题:我如何获得 new sdk_string(chars) 调用以调用第 3 方 dll? 但如果我对其他事情有误,那么其他事情我的问题是我错了。
更新:
仅供参考,以下是该类的整个 Dependency Walker 函数名称输出:
const sdk_string::`vftable'
class sdk_string & sdk_string::append(class sdk_string const &)
类 sdk_string & sdk_string::append(char)
类 sdk_string & sdk_string::append(char *)
类 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 &)
类 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)
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)
【问题讨论】:
-
我很好奇 DLL 甚至可以导出类。这是一件很不寻常的事情。它限制您使用与 DLL 目标相同的编译器和运行时。你能做到吗?但无论如何,您都可以按照您链接到的答案中的说明进行操作。我看不出是什么阻止了你。虽然,FWIW,Jared 的回答涉及将 C++ 类接口转换为通过 p/invoke 调用的扁平接口的非托管 C++ DLL。 Jared 没有描述 C++/CLI 方法,尽管 C++/CLI 可能是我解决这个问题的方式。
-
嗯,也许我在这里不想要一门课?我只是假设方法签名
foo::foo()等同于class foo{ public: foo(){} }。我想我错过了一些非常明显的难题......我如何将第 3 方 .dll 中的函数/类放入我的新 C++/CLR 包装器中以便我可以调用它?我读过有关使用LoadLibrary的信息,我在 C# 中没有问题,但只是不知道如何在 C++ 中执行。 -
创建包装器 c++/CLI dll 以代表您的 .NET 代码创建非托管对象是一回事;但是对于非托管代码然后调用非托管对象则完全不同。如果您打算直接调用该对象,则需要将 c++ 代码转换为 c++/CLI。当然,您将需要源代码。唯一的另一种方法是创建一个 c++/CLI proxy dll,其中包含您打算调用的 c++ 类方法的包装器方法。后者需要更多的工作,但它不需要需要更改原始 c++ 代码。
-
如果您可以访问 c++ 源代码,那么将其转换为 c++/CLI 比使用代理模式要容易得多,并且需要的维护也少得多。
-
很遗憾,我无权访问源代码或开发人员。
标签: c# visual-c++ dll pinvoke