首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从通用Lisp调用C++ (而不是C)?

从通用Lisp调用C++ (而不是C)?
EN

Stack Overflow用户
提问于 2009-09-05 05:16:46
回答 5查看 8.6K关注 0票数 15

我想知道是否存在从Common调用C++代码的方法(最好是可移植的,如果不是,最好在SBCL中调用,如果不是,那么可以使用Clozure、CLisp或ECL)。

C++将被调用到内部循环中进行数值计算,因此如果调用速度较快,那将是很好的选择。

CFFI似乎不支持这一点:

这个概念可以推广到其他语言;在编写本报告时,只有CFFI的C支持相当完整,但C++支持正在进行中。

(手册第4章)

SBCL的手册也没有提到C++,实际上它说

本章描述了SBCL与C程序和库的接口(而且,由于C接口是Unix世界的一种通用语言,一般也是其他程序和库的通用语言)。

C++代码使用OO和操作符重载,因此确实需要使用g++进行编译。

据我所知,我可以拥有一个C++ main()函数,并为C函数编写包装器,但情况并非如此--这是真的吗?

不管怎样..。有什么办法可以做到吗?

谢谢!

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-09-05 11:51:14

哦,等等!

似乎有一个把戏我可以使用!

我用C++编写了一个包装器,声明包装函数的外部是"C":

代码语言:javascript
运行
复制
#include "lib.h"

extern "C" int lib_operate (int i, double *x) {
...
}

可以从C和C++调用的头文件lib.h是:

代码语言:javascript
运行
复制
#if __cplusplus
extern "C" {
#endif

int lib_operate (int i, double *x);

#if __cplusplus
}
#endif

然后用以下方法编译:

代码语言:javascript
运行
复制
g++ -c lib.cpp
gcc -c prog.c
gcc lib.o prog.o -lstdc++ -o prog

似乎适用于玩具例子!:-)

因此,在通用Lisp中,我会在加载libstdc++之后调用包装器。

不管怎样,谢谢你的回答!

票数 7
EN

Stack Overflow用户

发布于 2009-09-05 05:25:34

编译后,大多数C++函数实际上归结为常规的C函数调用。由于函数重载和其他特性,C++编译器使用名称残缺来区分类似命名的函数。给定一个对象转储实用程序和关于C++编译器的足够知识,您可以直接从外部调用C++代码。

尽管如此,您可能会发现在Lisp和C++代码之间编写一个与C兼容的层会更容易。您可以像这样使用extern "C"这样做:

代码语言:javascript
运行
复制
extern "C" Foo *new_Foo(int x)
{
    return new Foo(x);
}

这使得new_Foo()函数遵循C调用约定,以便您可以从外部源调用它。

票数 17
EN

Stack Overflow用户

发布于 2009-09-05 05:59:05

除了名称mangling之外,调用C++函数而不是C函数的主要区别是“隐藏”特性,如这个指针,它们被隐式传递给成员函数。C运行时层对这些、隐式类型转换和其他有趣的C++特性一无所知,因此如果您打算通过C接口调用C++,则可能需要伪造这些特性。

假设您至少可以对要调用的对象及其所需的数据持有一个空*,则可以降级以下C++调用

代码语言:javascript
运行
复制
matrix->multiply(avector);

如果您创建一个C包装函数,则调用C:

代码语言:javascript
运行
复制
extern "C"
void matrix_multiply(void *cpp_matrix, void *cpp_vector) {
  reinterpret_cast<matrix_type *>(cpp_matrix)->multiply(reinterpret_cast<vector_type *>(cpp_vector);
}

显然,函数matrix_multiply将位于C++源代码中并按此方式编译,但它确实向外界公开了一个C接口。只要您能够与不透明的指针交互,您就可以接受上面的翻译提示。

诚然,对于这样的问题,这不一定是最优雅的解决方案,但我过去曾在类似您的情况下使用过它。

另一种选择是直接进行C++调用,方法是将它们作为具有附加参数的C调用处理,并自己提供所有所需的信息,但这确实会使您很快地进入编译器特定代码的领域。基本上,您仍然持有指向C++对象的不透明指针,但您必须计算出要调用的函数的损坏名称。一旦得到了函数名,就必须提供这个指针(在C++中是隐式的,在上面的示例中是半隐式的)和正确的参数,然后调用函数。这是可以做到的,但正如前面提到的,它使您深入到编译器领域,甚至是编译器版本特定的行为领域。

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1382529

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档