I am exploring the possibility of creating a Clutter binding for the D language ( http://d-programming-language.org/) and have started by trying some simple tests using dynamic loading of libclutter. I've run into a problem that might derive from the GObject inheritance system, and I'd appreciate any help getting it fi开发者_如何转开发gured out. Here's the rundown: using clutter_stage_get_default returns a ClutterActor* which I can use with the clutter_actor_* methods. But I always get errors or segfaults when I use the clutter_stage_* or clutter_container_* methods. Here's my test code: http://pastebin.com/nVrQ69dU
At the clutter_container_add_actor call on line 56, I get the following error:
(<unknown>:11976): Clutter-CRITICAL **: clutter_container_add_actor:
assertion 'CLUTTER_IS_CONTAINER (container)' failed
In example code, I have noticed the CLUTTER_STAGE and
CLUTTER_CONTAINER macros for casting (these obviously are not
available to me), but as far as I could tell, they simply performed
some checks, then did a plain C cast. If this is incorrect, and some
Gobject type magic needs to be done on the stage pointer before
casting, please let me know. Binding and using the
clutter_stage_set_title or clutter_stage_set_color with cast(ClutterStage*)stage
resulted in
segmentation faults, presumably the same issue.
EDIT: Here's a stripped down example with no external dependencies (if you're not on Linux, you'll need to replace the dl calls with your OS's equivalents). This code fails with a segfault, which according to GDB and Valgrind, is in clutter_stage_set_title (in /usr/lib/libclutter-glx-1.0.so.0.600.14)
The problem is that you don't declare the C functions as extern(C)
. Because of that dmd thinks you're calling a D function and uses the wrong calling convention. One way to do this correctly is like this:
alias extern(C) void function(void*, const char*) setTitleFunc;
auto clutter_stage_set_title = getSym!(setTitleFunc)("clutter_stage_set_title");
I'm not sure how to make it work without the alias though. DMD refuses to parse anything with extern(C)
in a template parameter:
auto clutter_stage_set_title = getSym!(extern(C) void function(void*, const char*))("clutter_stage_set_title"); //Doesn't work
BTW: Your cstring
function is dangerous: It returns a char* indicating that the string can be modified, but this is not always true: If you pass a string literal to toStringz
it might not allocate new memory but return the pointer of the original string instead. String literals are in readonly memory, so this could lead to problems.
You could just adjust your function types to match the C Types (const gchar*
in C --> const char*
in D) and use toStringz directly.
structs in D cannot inherit from each other and casting struct pointers will return null unless there's a intermediate cast to I got refuted herevoid*
(unlike a C cast)
you're better off adding another abstraction layer using handle-wrapping structs and emulating the checks from those macros when casting
but what happens if you do
clutter_container_add_actor(cast(ClutterContainer*)(cast(void*)stage), textbox);
(casting to void* first and then to ClutterContainer*)
精彩评论