在数字化转型中,选择合适的跨平台开发框架不仅能提高效率,还有助于确保数据安全与合规性。
876
2022-12-01
d与C++互操作
为什么是D?
强类型系统编程语言原型立即投入生产 最佳C++集成,出色的C集成
支持的特征
几乎所有东西class/struct,ref,指针,const,nothrow... 模板(!)重载运算符(!!) 异常(!!!)
第0步,组织
+agora |-dub.json |-source/agora |-source/scpd |-source/scpp
第一步:构建系统
"preGenerateCommands": [ "$DUB --verbose --single scripts/build_scpp.d" ], "sourceFiles-posix": [ "source/scpp/build/*.o" ], "sourceFiles-windows": [ "source/scpp/build/*.obj" ], "versions": [ "_GLIBCXX_USE_CXX98_ABI" ], "dflags": [ "-extern-std=c++17" ], "lflags-posix": [ "-lstdc++" ],
第 2 步:了解目标
//目标:CppRuntime_Clang => OSX, Linux, WindowsCppRuntime_Gcc => Linux (OSX in the future?)CppRuntime_Microsoft =>
第3步:简单的东西
extern(C++) struct Foo { int a; }extern(C++) void func1 (ref const(Foo) f);extern(C++) void func2 (const(Foo*) f);extern(C++) void func3 (const(Foo**) f);//struct Foo { int a; };void func1 (Foo const& f);void func2 (Foo const* f);// void func2 (Foo const* const f);void func3 (Foo const* const* f);
D代码:遵循D规则
名字空间:
extern(C++, "dlang", "awesome", "app") void awesomeFunc ();// 不要这样:extern(C++, dlang.awesome.app) void lessAwesome ();static assert( lessAwesome.mangleof == dlang.awesome.app.lessAwesome.mangleof);
更灵活的名字空间:
version (CppRuntime_Clang) enum StdNamespace = AliasSeq!("std", "__1");else enum StdNamespace = "std";// 注意括号public extern(C++, (StdNamespace)) struct equal_to (T = void) {}
简单方便:
public extern(C++, (StdNamespace)) struct pair (T1, T2){ T1 first; T2 second;}
注意:混杂|虚表/偏移|大小|生命期函数(ctor/dtor/copy/move).混杂用pragma(mangle, str).虚表/偏移|大小通过测试,生命期用ref/指针/包装器.
测试大小
static foreach (Type; GlueTypes) extern(C++) ulong cppSizeOf (ref Type);/// 检查大小unittest{ foreach (Type; GlueTypes) { Type object = Type.init; assert(Type.sizeof == cppSizeOf(object), format("'%s'的类型大小不匹配: %s (D) != %s (C++)",Type.stringof, Type.sizeof, cppSizeOf(object))); }}
测试布局
/// 构内包含字段的`大小/偏移`.extern(C++) struct FieldInfo { long size, offset; }static foreach (Type; GlueTypes) extern(C++) FieldInfo cppFieldInfo (ref Type, const(char)*);
再来:
/// 检查C++构/对象的大小和布局unittest{ foreach (Type; TypesWithLayout) foreach (idx, field; Type.init.tupleof) { auto object = Type.init; auto field_info = cppFieldInfo(object, Type.tupleof[idx].stringof.toStringz); assert(typeof(field).sizeof == field_info.size,format("'%s'的'%s'字段大小不匹配: %s (D) != %s (C++)", Type.tupleof[idx].stringof, Type.stringof, typeof(field).sizeof, field_info.size)); assert(Type.tupleof[idx].offsetof == field_info.offset, format("'%s'的'%s'的偏移不匹配: %s (D) != %s (C++)", Type.tupleof[idx].stringof, Type.stringof, Type.tupleof[idx].offsetof, field_info.offset)); }}
标::映射
#include
标::映射在D端:
extern(C++, class):struct Map (Key, Value) { extern(D) void opIndexAssign (Value value, const Key key) { this.insertOrAssign(key, value); } static Map* make (); ref Value opIndex (ref const Key key); private void insertOrAssign(const ref Key, const ref Value);}
应该变这样:
#include
绑定std
当前在core.stdcpp,将转移到另一个库.allocator, array, vector, string, exception, memory, string_view...,但无map.
C++包装器代码
序号 | |
| 你需要它(来 |
| 你最强大的 |
| 按 |
| 奇怪的 |
逐步替换C++
替换单个函数很容易,替换方法也很简单,清除依赖/提高代码质量的简单方法:
整合C++的特征
extern(C++, [class|struct])extern(C++, ident|expression)core.attributes : gnuAbiTagpragma(mangle, str_or_decl, [str])__traits(getTargetInfo, "something")
及,复制构造器/内部指针(串),及DWARF异常处理.
哪些有用
序号 | 有用点 |
| 良好的 |
| 开始就有的额外 |
| |
| 按 |
| 手工制作,及基本 |
| |
| 不使用 |
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~