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
.