【发布时间】:2014-11-18 02:30:09
【问题描述】:
我正在尝试在 OpenTK 中使用 SPARK 粒子系统。
我的项目包含文件夹中的头文件,只有两个头文件,其中仅包含其他头文件,并且文件夹也包含源文件。
到目前为止,我已经尝试了几种方法,但没有任何方法对我有用,这些是我尝试过的:
1。 P/调用
这是在您的 C++ 项目中编写一些代码来构建 dll,然后在 C# 中使用DllImport 属性(显然需要using System.Runtime.InteropServices;)。我发现这不适用于类的困难方式,它只适用于类外的方法,所以这种方法是无效的。
2。包装类
这是编写一个包含指向原始类的指针的类。我发现困难实际上来自于从托管代码调用非托管代码(没有自动内存管理),这就是需要包装类的原因,这就是为什么您必须重新定义方法的签名并让它们调用原始方法的原因。
当然这有好处,比如以更好的方式命名类和方法,但是库太大了,你可以看到这样做的努力。
3。使用自动包装器:
这是一个很好的方法,尤其是对于 xInterop++。我对此非常乐观,并认为它会起作用,它说“给我 .h 文件和 dll,我会为你构建 .NET dll”。很好,但这样做会出错;简而言之:
您必须确保 .h 文件和 dll 是一致的,并且 库在 C++ 项目中工作。
我已经尝试了几种方法来处理这个错误:
- 了解 dll 包含的内容:我从谷歌搜索和从这个网站了解到这很困难,所以我的尝试失败了。
- 将头文件放入新项目并构建它:收到错误,修复它们,然后构建项目,它运行良好。我将带有头文件的 dll 文件上传到 xInterop。然后它告诉找到的类,但会说什么也没找到!我搜索并了解到编译器必须通过使用以下语句标记所需的每个类来告诉编译器需要由dll公开哪些类:
_declspec(dllexport)。 - 我使用 Find & Replace 修复了这个问题并再次尝试并显示了类,所以我启动了 xInterop 并收到了同样的错误。
- 它要求确保 dll 正常工作。在验证文件工作正常后,我启动了程序并产生了链接器错误。
这是我卡住的地方,这些是我得到的链接器错误:
main.obj:错误 LNK2019:无法解析的外部符号“void __cdecl SPK::swapParticles(类 SPK::粒子 &,类 SPK::粒子 &)" (?swapParticles@SPK@@YAXAAVParticle@1@0@Z) 在函数中引用 “私有:void __thiscall SPK::Pool::swapElements(类 SPK::Particle &,类 SPK::Particle &)" (?swapElements@?$Pool@VParticle@SPK@@@SPK@@AAEXAAVParticle@2@0@Z) main.obj:错误 LNK2001:未解析的外部符号“unsigned int” SPK::randomSeed" (?randomSeed@SPK@@3IA) main.obj:错误 LNK2001: 未解析的外部符号“unsigned long const SPK::NO_ID” (?NO_ID@SPK@@3KB) main.obj:错误 LNK2001:未解析的外部符号 “公共:静态浮点常量 * 常量 SPK::Transformable::IDENTITY” (?IDENTITY@Transformable@SPK@@2QBMB)
这是产生这些错误的代码:
#include "Extensions/Emitters/SPK_RandomEmitter.h"
using namespace SPK;
int main()
{
RandomEmitter e;
e.changeFlow(6);
e.getFlow();
return 0;
}
所以这是我的问题,我很抱歉解释太多,但我已经进行了三天的搜索,但没有找到任何解决方案。
PS:
库很大,所以必须使用自动解决方案。
【问题讨论】:
-
我认为你将不得不自己学习如何进行互操作,我可以推荐一个优秀的资源Expert C++/CLI
-
@ChrisO 我不知道为什么,但是亚马逊链接打不开。
-
Marcus Heege 的专家 C++/CLI。它可能会帮助您了解 P/Invoke 实际上有两种风格,显式和隐式。 See this intro article on Wikipedia 了解这两种类型之间的差异的一个很好的起点。根据 SPK DLL 的函数签名,可能无法使用显式版本的 P/Invoke。一个常见的例子,如果函数使用
std::basic_string,那么你将不得不编写一个自定义的 C++/CLI 包装器来进行封送处理。 -
@ChrisO 所以没办法了?当你有一个大库时,编写自定义包装器很困难。
-
如果您确实需要使用类并且您无法导出它们,您可以将充当包装器的普通函数导出到类。示例:ideone.com/at1FT5
标签: c# c++ dll wrapper language-interoperability