Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
November 02, 2015 Access violation when calling C DLL from D | ||||
---|---|---|---|---|
| ||||
Hi, I am trying to write a simple interface to the MRuby Ruby interpreter so I can use ruby scripts in my D program. I was able to get MRuby compiled as a DLL without too much difficulty, but the headers are very long and complicated, and porting them entirely to D would be a huge project in and of itself. I am trying to get by with only what I need, so here is what I have so far: module script.mruby; alias mrb_bool = bool; alias mrb_int = int; alias mrb_float = double; alias mrb_sym = uint; alias mrb_aspec = uint; struct mrb_value { } struct RObject { } struct RClass { } struct mrb_value { } struct mrb_state { } extern(C) char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr); extern (C) mrb_value mrb_load_string(mrb_state *mrb, const char *s); extern (C) mrb_value mrb_load_nstring(mrb_state *mrb, const char *s, int len); extern (C) mrb_state *mrb_open(); extern (C) void mrb_close(mrb_state *mrb); In theory, this should be enough to test that MRuby is working, so I tried to run the following code: mrb = mrb_open(); mrb_value result = mrb_load_string(mrb, toStringz("String('test')")); Log.info(to!string(mrb_string_value_cstr(mrb, &result))); But the result was: object.Error@(0): Access Violation I wasn't able to get the Visual D debugger to trace into the code, but after some investigation, I figured out that the error was occurring in the strlen runtime function. I don't think I did anything wrong with the way I passed a string into the mrb_load_string function, so I am kind of at a loss as to what the problem might be. |
November 02, 2015 Re: Access violation when calling C DLL from D | ||||
---|---|---|---|---|
| ||||
Posted in reply to AnoHito | On Monday, 2 November 2015 at 01:02:45 UTC, AnoHito wrote: > [...] > the headers are very long and complicated, and porting them entirely to D would be a huge project in and of itself. > [...] You can give a try at h2d, the C header to D interface converter: http://dlang.org/htod.html |
November 02, 2015 Re: Access violation when calling C DLL from D | ||||
---|---|---|---|---|
| ||||
Posted in reply to BBasile | On Monday, 2 November 2015 at 02:13:29 UTC, BBasile wrote:
> On Monday, 2 November 2015 at 01:02:45 UTC, AnoHito wrote:
>> [...]
>> the headers are very long and complicated, and porting them entirely to D would be a huge project in and of itself.
>> [...]
>
> You can give a try at h2d, the C header to D interface converter:
>
> http://dlang.org/htod.html
I did, but it just produced a ton of errors...
|
November 02, 2015 Re: Access violation when calling C DLL from D | ||||
---|---|---|---|---|
| ||||
Posted in reply to AnoHito | On Monday, 2 November 2015 at 01:02:45 UTC, AnoHito wrote: > Hi, I am trying to write a simple interface to the MRuby Ruby interpreter so I can use ruby scripts in my D program. I was able to get MRuby compiled as a DLL without too much difficulty, but the headers are very long and complicated, and porting them entirely to D would be a huge project in and of itself. I am trying to get by with only what I need, so here is what I have so far: > > module script.mruby; > > alias mrb_bool = bool; > alias mrb_int = int; > alias mrb_float = double; > alias mrb_sym = uint; > > alias mrb_aspec = uint; > > struct mrb_value > { > > } > struct RObject > { > > } > > struct RClass > { > > } > > struct mrb_value > { > > } > > struct mrb_state > { > > } > > extern(C) char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr); > > extern (C) mrb_value mrb_load_string(mrb_state *mrb, const char *s); > extern (C) mrb_value mrb_load_nstring(mrb_state *mrb, const char *s, int len); > > extern (C) mrb_state *mrb_open(); > extern (C) void mrb_close(mrb_state *mrb); > In D the unary * is left associative NOT right. i.e. write int* a,b,c; // a,b and c are all int* NOT int*, int,int as would be the case in C because you are not allowed to change the type during the declaration. > In theory, this should be enough to test that MRuby is working, so I tried to run the following code: > > mrb = mrb_open(); > mrb_value result = mrb_load_string(mrb, toStringz("String('test')")); string literals are automatically null terminated, no need to `toStringz`. if it was not a literal the you would have to. > Log.info(to!string(mrb_string_value_cstr(mrb, &result))); > > But the result was: > > object.Error@(0): Access Violation > (0) suggests a null pointer > I wasn't able to get the Visual D debugger to trace into the code, but after some investigation, I figured out that the error was occurring in the strlen runtime function. I don't think I did anything wrong with the way I passed a string into the mrb_load_string function, so I am kind of at a loss as to what the problem might be. and the only operation here likely to call strlen is to!string from a char* (since D strings know their length) perhaps you should inspect the value returned from mrb_string_value_cstr few possible places to look alignment - are the types declared in c declared with an alignment? check the values of mob and result Also take a Look at DStep on github for auto translation of C |
November 02, 2015 Re: Access violation when calling C DLL from D | ||||
---|---|---|---|---|
| ||||
Posted in reply to AnoHito | On Monday, 2 November 2015 at 02:30:09 UTC, AnoHito wrote: > On Monday, 2 November 2015 at 02:13:29 UTC, BBasile wrote: >> On Monday, 2 November 2015 at 01:02:45 UTC, AnoHito wrote: >>> [...] >>> the headers are very long and complicated, and porting them entirely to D would be a huge project in and of itself. >>> [...] >> >> You can give a try at h2d, the C header to D interface converter: >> >> http://dlang.org/htod.html > > I did, but it just produced a ton of errors... Try this instead: https://github.com/jacob-carlborg/dstep It's been used to convert C Ruby declarations to D: https://github.com/jacob-carlborg/orbit/tree/master/ruby Atila |
November 02, 2015 Re: Access violation when calling C DLL from D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Atila Neves | On Monday, 2 November 2015 at 15:56:20 UTC, Atila Neves wrote: > Try this instead: > > https://github.com/jacob-carlborg/dstep > > It's been used to convert C Ruby declarations to D: > > https://github.com/jacob-carlborg/orbit/tree/master/ruby > > Atila I might try it later, but I don't think the header conversion is the problem in this case. I tried to get some insight into what was happening by modifying the mrb_load_nstring function: MRB_API mrb_value mrb_load_nstring(mrb_state *mrb, const char *s, int len) { FILE *f = fopen("output.txt", "w"); fprintf(f, "mrb: %p, s: %p, len: %i\n", mrb, s, len); fclose(f); return mrb_load_nstring_cxt(mrb, s, len, NULL); } The output was: mrb: 0052E818, s: 0000000E, len: 5 That was... odd. I tried to modify my extern statement a bit: extern (C) mrb_value mrb_load_nstring(void *junk, mrb_state *mrb, const char *s, int len); And ran the following code: mrb = mrb_open(); mrb_value result = mrb_load_nstring(cast(void *) 0, mrb, toStringz("String('test')"), 14); Log.info(to!string(mrb_string_value_cstr(mrb, &result))); This time the result was: mrb: 0039E750, s: 0052E818, len: 14 Things actually got a little further now that the values were getting passed correctly(?) but another null pointer access violation got triggered later on in the code. So something weird is definitely going on here. Is there something that needs to be done differently to handle the calling conventions here? I think all the functions in MRuby that I have attempted to call so far are regular cdecl functions. Here is the definitions of MRB_API from the original header, in case it sheds any light on things: #if defined(MRB_BUILD_AS_DLL) #if defined(MRB_CORE) || defined(MRB_LIB) # define MRB_API __declspec(dllexport) #else # define MRB_API __declspec(dllimport) #endif #else # define MRB_API extern #endif Could the problem be because I used mingw to build the DLL, and Visual D to build my main project? It was more or less necessary, since Visual Studio's build tools couldn't handle the MRuby build scripts. I didn't think it should cause any problems, but maybe I was wrong. Also, here is the command I used to generate the lib for the DLL: implib /s mruby.lib mruby.dll Is implib still the best tool for doing this? The only version I was able to find was very old, so maybe it is not generating the lib files correctly. |
November 03, 2015 Re: Access violation when calling C DLL from D | ||||
---|---|---|---|---|
| ||||
Posted in reply to AnoHito | Okay, I finally got it working. The problem was that mrb_value needed to be fully defined in order for my code to work, because it was being passed on the stack directly instead of by a pointer: struct mrb_value { union { mrb_float f; void* p; mrb_int i; mrb_sym sym; } mrb_vtype tt; } |
Copyright © 1999-2021 by the D Language Foundation