关于 d:将 ClutterActor* 投射到 ClutterStage*

Casting ClutterActor* to ClutterStage*

我正在探索为 D 创建 Clutter 绑定的可能性
语言(http://d-programming-language.org/)并开始于
尝试使用动态加载 libclutter 进行一些简单的测试。我跑了
可能源自 GObject 继承的问题
系统,我将不胜感激任何帮助解决它。这里是
rundown:使用 clutter_stage_get_default 返回一个 ClutterActor*
我可以使用 clutter_actor_* 方法。但我总是得到错误或
当我使用 clutter_stage_* 或 clutter_container_* 时出现段错误
方法。这是我的测试代码:http://pastebin.com/nVrQ69dU

在第 56 行的 clutter_container_add_actor 调用中,我收到以下错误:
(<unknown>:11976): Clutter-CRITICAL **: clutter_container_add_actor:
assertion 'CLUTTER_IS_CONTAINER (container)' failed

在示例代码中,我注意到 CLUTTER_STAGE 和
用于强制转换的 CLUTTER_CONTAINER 宏(这些显然不是
可用),但据我所知,他们只是表演
一些检查,然后做了一个普通的 C 转换。如果这是不正确的,并且一些
Gobject类型魔术需要在舞台指针上完成
铸造,请告诉我。绑定和使用
带有 cast(ClutterStage*)stage 的 clutter_stage_set_title 或 clutter_stage_set_color 导致
分段错误,大概是同一个问题。

编辑:这是一个没有外部依赖的精简示例(如果您不在 Linux 上,则需要将 dl 调用替换为您的操作系统的等效项)。此代码因段错误而失败,根据 GDB 和 Valgrind,该段错误位于 clutter_stage_set_title (in /usr/lib/libclutter-glx-1.0.so.0.600.14)


问题在于您没有将 C 函数声明为 extern(C)。因为 dmd 认为您正在调用 D 函数并使用错误的调用约定。正确执行此操作的一种方法是:

1
2
alias extern(C) void function(void*, const char*) setTitleFunc;
auto clutter_stage_set_title = getSym!(setTitleFunc)("clutter_stage_set_title");

我不确定如何在没有别名的情况下使其工作。 DMD 拒绝解析模板参数中带有 extern(C) 的任何内容:

1
auto clutter_stage_set_title = getSym!(extern(C) void function(void*, const char*))("clutter_stage_set_title"); //Doesn't work

顺便说一句:您的 cstring 函数很危险:它返回一个 char* 表示可以修改字符串,但这并不总是正确的:如果您将字符串文字传递给 toStringz 它可能不会分配新内存,但而是返回原始字符串的指针。字符串文字位于只读内存中,因此这可能会导致问题。

您可以调整您的函数类型以匹配 C 类型(C 中的 const gchar* --> D 中的 const char*)并直接使用 toStringz。


D 中的结构不能相互继承,并且转换结构指针将返回 null,除非有对 void* 的中间转换(与 C 转换不同) 我在这里被驳斥了

最好使用句柄package结构添加另一个抽象层,并在转换时模拟这些宏的检查

但是如果你这样做会发生什么

1
clutter_container_add_actor(cast(ClutterContainer*)(cast(void*)stage), textbox);

(先转换为 void*,然后转换为 ClutterContainer*)