我正在为LLVM中的特殊用途语言编写编译器。我想为已经用C ++编写的库添加绑定。我的想法是将库编译为LLVM字节码(使用clang -emit-llvm -S abc.c
)并在编译期间将其链接。这适用于像
// lib.c
int f() {
return 123;
}
但是库的一部分写得像
// A.cc
class A {
public:
int f() { return 123; }
};
导致空字节码文件。我知道我可以通过分离实现来解决这个问题:
// A.cc
class A {
public:
int f();
};
int A::f() {
return 123;
}
但这将是一项繁琐的工作。有没有办法从我的库源创建有用的字节码呢?或者在我的编译器中使库可用的任何其他方法?
答案 0 :(得分:6)
您可以看到clang是否尊重显式模板实例化的外部链接。这可能适用于非模板,但您可以“强迫它”用于模板。
简单概要:
template <typename T=int>
struct ATemplate { T f() { return 123; } };
添加文件 lib1_instantiate.cpp
#include "lib1.h"
template struct ATemplate<int>;
template struct ATemplate<unsigned int>;
template struct ATemplate<long>; // etc.
这应该使用外部链接实例化命名模板。
如果您遇到非模板类,并且上面的技巧不起作用,您可以像这样包装它:
<强> instantiate.cpp:
强>
namespace hidden_details
{
template <class libtype> struct instantiator : public libtype
// derives... just do something that requires a complete type (not a forward!)
{ };
}
template struct hidden_details::instantiator<A>;
如果运气不好,您必须“使用”内联成员才能获得外部链接。一个常见的技巧是使用这些成员的地址(您不需要实现委托的东西):
<强> instantiate.cpp:
强>
static void force_use_A()
{
void* unused = (void*) &A::f;
}
然而
HTH
答案 1 :(得分:0)
如果只想使用一些库函数,则可以使用另一种方法:为您使用的所有内容创建一个包装器。
// wrapper.cc
A* A_create() {
return new A();
}
// and so on
这样你就不必修改你的库了,但这绝对是一些额外的输入。