d与C++的绑定的Calypso工具
Calypso工具,地址
它的工作方式与htod.exe类似,Calypso生成extern(C++).
它与clang++绑定在一起.
这不是Calypso现在的工作方式,它通过'modmap(C++)"dll头文件.h"',直接从D模块导入C++头文件,而不生成中间的D绑定模块:
这里,基础c++绑定生成,用来生成qt绑定.
好unwashed会把D看作是一种只在clang++支持的平台上才可行的语言.Qt/vtk/数字库.
目标是让Qt,VTK,线性代数,矩阵等都能在D(Linux和Windows)中使用,我并不担心它是如何完成的
Calypso需要dmd+clang++是自然的.与extern(C++)是帮助,而不是替代关系.
编译器支持插件.
在Ogre3D演示的第一道曙光之后,异常捕捉是下个任务,Clang可能会大大简化C++异常的处理.
1.在D中无法抓C++非多态类型异常.
2.(或Calypso)为从C++抛的多态类型定义了D类对应项,特别是std::exception和subtypes.注意,这些是D类,而不是D构.
3.D代码可抓std::exception.唯一注意,抓的异常无法在catch语句之后继续存在.考虑到调用C++并不是首要安全问题,这是合理折中.示例:
import core.stdcpp.vector;
import core.stdcpp.exception;
core.stdcpp.exception g;
void fun(core.stdcpp.vector!int v)
{
try
{
v.push_back(42);
}
catch (core.stdcpp.exception e) // 可抓
{
g = e; // 悬挂
}
}
README现在应该更清楚Calypso应做什么,有用模板部分和显式规范示例改进和扩展的展示例的链接,并解释了如何构建它并链接到C++库.
假定,
//test.cpp
int foo(unsigned *p);
如何使用Calypso与D?
...这里发生了什么?
uint x;
foo(&x);
然后是:
$ clang++ -std=c++11 -c showcase.cpp -o showcase.cpp.o
$ ar rcs libshowcase.a showcase.cpp.o
$ ldc2 -cpp-args -std=c++11 -Llibshowcase.a -L-lstdc++ showcase.d
Calypso是ldc2的一部分,据我所知,是通过"-cpp-args"壳参数调用的.
下面是最简单说明如何使用上面函数的示例:
//test.h
namespace test {
int foo(unsigned int *p);
}
//test.cpp
#include "test.h"
int test::foo(unsigned int *p)
{
return *p * 2;
}
//test.d
modmap(C++) "test.h";
import(C++) test._; //导入全局变量,函数和`typedef`
import std.stdio;
void main()
{
uint x = 4;
writeln("foo = ", foo(&x));
}
我测试过更复杂示例,运行得很好.目前,我在Calypso中遇见的最大的警告是,所有东西都必须在一个名字空间中.因此test.h有一个有点多余的"test"名字空间.据我所知,要使用Calypso,必须有它.
导入'C++'库时,如果只使用.h文件(如包含一些类的美化的C头文件)或类似,不封装在唯一的名字空间中,这是个问题.
-cpp-args仅用于在生成预编译头时传递参数给Clang.
Calypso把自己注册为"语言插件",当parse.c遇到import(ABC)xxx.yyy时;它询问是否注册有处理"ABC"语言的插件.如果有,它让插件创建Import符号,如Calypso创建了从Import继承的cpp::Import,并且有个不会在.d文件中查找模块而是在Clang生成的PCH中查找模块的完全不同的load()方法.
下面是LangPlugin接口:
class LangPlugin
{
public:
//如果`此插件`不处理所述语言,返回`-1`,否则返回传递给createImport的`id`号
virtual int doesHandleModmap(const utf8_t *lang) = 0;
virtual Modmap *createModmap(int langId,Loc loc, Expression *arg) = 0;
//如果`此插件`不处理所述树,返回`-1`,否则返回传递给createImport的`id`号
virtual int doesHandleImport(const utf8_t *tree) = 0;
virtual Import *createImport(int treeId,Loc loc, Identifiers *packages, Identifier *id,Identifier *aliasId, int isstatic) = 0;
// ===== - - - - - ===== //
virtual Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,Expression *e1, Declaration *var, int flag = 0) = 0;
// ===== - - - - - ===== //
virtual FuncDeclaration *buildDtor(AggregateDeclaration *ad, Scope *sc) = 0;
virtual FuncDeclaration *buildCpCtor(StructDeclaration *sd, Scope *sc) = 0;
// ===== - - - - - ===== //
virtual CodeGen *codegen() = 0;
};
getRightThis,buildDtor和buildCpCtor是必须的,因为它们"覆盖"了具有相同名称的全局函数.
Andrei通用插件系统问题,我不知道如何构建.为Calypso创建的钩子是C++特有的,只是简单开放钩子(并不是真正的侵入性,除了一两个可能会以不同的方式完成的钩子,也不会使代码丑陋):勾挂只是强制复制冗余基函数,对大的语义函数,很差.
使用结构不是更容易吗?它们只缺少一个继承特性,而类缺少值类型所必需的许多特性:值类型和确定性析构.
工作原理如下:
给定C++头文件foo.h:
void bar(unsigned *);
和C++源文件foo.cpp:
void bar(unsigned *p) { }
我想在从test.d中调用bar():
void main() {
uint x;
bar(&x);
}
以下是如何使用Calypso:
module test;
modmap (C++) "foo.h";
import (C++) _ : bar;
void main() {
uint x;
bar(&x);
}
要编译和链接:
clang++ foo.cpp -c
ldc test.d foo.o
生成可运行的"test"程序.
Calypso不是独立的工具.它是LDC允许你在不需要绑定或中间文件,就直接导入/包含,C++头文件,并使用D中的声明的一个分支.
可不必编写绑定直接对接C++库的经过修改的LDC.
浙公网安备 33010602011771号