【发布时间】:2009-04-20 05:27:46
【问题描述】:
有没有人用 Java 或 .NET 成功地“封装”了一个 C++ API?我有一个应用程序,它提供了用于编写插件的 C++ API。我想做的是从 .NET 或 Java 访问该 API。
我需要使用 COM,还是有更简单/更好的替代方案?
【问题讨论】:
有没有人用 Java 或 .NET 成功地“封装”了一个 C++ API?我有一个应用程序,它提供了用于编写插件的 C++ API。我想做的是从 .NET 或 Java 访问该 API。
我需要使用 COM,还是有更简单/更好的替代方案?
【问题讨论】:
如果您有一个非常直接的方法签名(即采用和返回原始类型的方法,例如 int、char[]、void* ... 等),那么在 .NET 中执行此操作相当容易并且仍然可行但是在 Java 中使用 JNI 有点困难。
但是,如果您的类方法使用现代 C++ 编程技术,例如 boost 共享指针和 STL 容器,那么情况就完全不同了。在这种情况下,您需要非常小心内存管理。
编辑: 如果该方法具有 C++ 模板参数会更有趣,因为 C++ 模板系统与 C# 或 Java 泛型非常不同,因为它只是一个编译时机制。基本上,这意味着每次将不同的数据类型传递给模板参数时,方法或类的签名都是不同的。这使得该方法无法用 C# 或 Java 包装。
【讨论】:
我认为您可能会要求类似于Java Native Inferface 的内容,它允许您调用用 C++ 等语言编写的代码。我从来没有使用过它。但你可能想检查一下。希望对您有所帮助。
【讨论】:
在 Java 方面,这里有很多选项 ..this question 实际上与您正在寻找的非常接近,前提是您的 API 可以封装在 DLL、com 或 activex 对象中。
我个人使用 JIntegra 将 API 调用包装到 office (Word) 并直接在 Java 中使用它。确实需要一些黑客来获得所需的功能,但我们最终使它工作。摆弄其实是在Word端,实际集成还是比较容易的。
【讨论】:
如果您打算使用 .NET,我建议您创建一个C++/CLI wrapper。 C++/CLI 让你mix the managed .NET code with native C++ code。这种方法有一些技巧,但在大多数情况下效果很好。
Wikipedia entry 也有一些不错的链接。
【讨论】:
使用 SWIG 处理 JNI 内容使得包装 cpp API 并从 Java 中使用它变得非常轻松。
【讨论】:
我是SlimDX 的主要作者。它可能不是目前最大的开源互操作性项目,但在整个项目的 150K+ 行中,它是相当可观的。它是使用 C++/CLI 编写的,这是一种 Microsoft 开发的语言,很大程度上与 C++ 兼容,旨在允许您构建包装器。它工作得很好,但需要注意的是它仅适用于 Windows。 Mono不会接受它。我不知道这对您有多大影响,但它可能是比 COM 更好的选择。不幸的是,您基本上必须自己想出很多提示和技巧。我本来打算在博客上介绍我们在 SlimDX 上使用的很多东西,但不知怎的,我从来没有完全解决它。
在Java方面,我相信你必须使用JNI。祝你好运。我从来没有和任何与 JNI 合作过的人交谈过,而我们俩都笑了,以一种糟糕的“哎呀,伤害”的方式。
【讨论】:
我维护的软件是用 C++ 实现的,但必须具有多种语言的接口,包括 Java 和 .NET,还包括 delphi 和 VB6。另外,它必须在多个平台上工作(所以 Java 需要在 unix 上工作)。
这样做的方式是使用单个 DLL 导出使用原始类型的普通 C 函数。例如,给定一个类 Foo:
long MY_EXPORT_FLAG FooCreate()
{
return (long)new Foo();
}
void MY_EXPORT_FLAG FooDestroy(long Handle)
{
delete (Foo*)Handle;
}
void MY_EXPORT_FLAG BarMethod(long Handle, const char* pStr1, long* pReturnValue)
{
*pReturnValue = ((Foo*)Handle)->BarMethod( pStr1 );
}
然后您的 JNI/.NET/VB6/Delphi 代码实现语言特定的类包装器,但调用这些 C dll 函数。每个类包装器都包含一个句柄,并将其传递给 C 函数。
这很有效,因为大多数语言都倾向于使用 C 作为最低公分母,因此只要您可以通过精简的 C api 导出接口,您就可以为其他语言构建接口。
我们在 DLL 中导出 C(而不是 C++)api,因为函数签名跨平台更加标准化。
不要忘记,在 C# 和 Java 上,您必须处理多字节字符串编码,因此您应该弄清楚如何将字符串转码到 C++ 代码/从 C++ 代码转码。这通常涉及了解语言环境,或者您可以便宜并只支持 UTF-8。
【讨论】: