digitalmars.D.learn - Binding to C - Arrays and Access Violation
- jmh530 (31/31) Feb 02 2016 I'm working on generating a binding to a C library. I've got the
- biozic (7/39) Feb 02 2016 Is grad allocated in the D code? If so, it could have been
- jmh530 (2/8) Feb 02 2016 grad is only created in the C code. I don't pass it myself.
- Mike Parker (12/25) Feb 02 2016 The parameter to the C function should be declared as extern(C),
- jmh530 (11/22) Feb 02 2016 Success! Couldn't have done it without your help.
- Mike Parker (12/18) Feb 03 2016 extern(C) is only used with function pointers when it's needed.
I'm working on generating a binding to a C library. I've got the .h file converted and can call some parts of the library with no errors. However, I have reached a stumbling block in a critical part. The library requires passing function pointers to various functions in the library. When I try to run these functions, I get an Access Violation error. I enabled additional DMD warnings, which helped pinpoint the issue. My D code calls a C function. One of the parameters to the C function is a function pointer to a D function. This D function (below) is one that I copied from the C library's tutorial. I only slightly changed the signature. This function is eventually called in other functions in the C library. double myfunc(uint n, const double* x, double* grad, void* my_func_data) { if (grad) { grad[0] = 0.0; grad[1] = 0.5 / sqrt(x[1]); } return sqrt(x[1]); } The line (though likely the next will too) that causes a problem is grad[0] = 0.0; Thus, as it is an Access Violation, I'm guessing the issue is with accessing elements of arrays in the D function from the C function. I don't know. When I try to call the D function in D, it works, but I have to refer to x and grad as x.ptr and grad.ptr. I'm not sure how to go about fixing this...
Feb 02 2016
On Tuesday, 2 February 2016 at 22:56:28 UTC, jmh530 wrote:I'm working on generating a binding to a C library. I've got the .h file converted and can call some parts of the library with no errors. However, I have reached a stumbling block in a critical part. The library requires passing function pointers to various functions in the library. When I try to run these functions, I get an Access Violation error. I enabled additional DMD warnings, which helped pinpoint the issue. My D code calls a C function. One of the parameters to the C function is a function pointer to a D function. This D function (below) is one that I copied from the C library's tutorial. I only slightly changed the signature. This function is eventually called in other functions in the C library. double myfunc(uint n, const double* x, double* grad, void* my_func_data) { if (grad) { grad[0] = 0.0; grad[1] = 0.5 / sqrt(x[1]); } return sqrt(x[1]); } The line (though likely the next will too) that causes a problem is grad[0] = 0.0; Thus, as it is an Access Violation, I'm guessing the issue is with accessing elements of arrays in the D function from the C function. I don't know. When I try to call the D function in D, it works, but I have to refer to x and grad as x.ptr and grad.ptr. I'm not sure how to go about fixing this...Is grad allocated in the D code? If so, it could have been collected because the GC lost track of its use when passing to and from the C code. Or is grad owned by the C code? If so, either there is a bug in the library or it's misused, because its memory has been freed/has never been allocated/has gone out of scope.
Feb 02 2016
On Wednesday, 3 February 2016 at 00:28:24 UTC, biozic wrote:Is grad allocated in the D code? If so, it could have been collected because the GC lost track of its use when passing to and from the C code. Or is grad owned by the C code? If so, either there is a bug in the library or it's misused, because its memory has been freed/has never been allocated/has gone out of scope.grad is only created in the C code. I don't pass it myself.
Feb 02 2016
On Tuesday, 2 February 2016 at 22:56:28 UTC, jmh530 wrote:My D code calls a C function. One of the parameters to the C function is a function pointer to a D function. This D function (below) is one that I copied from the C library's tutorial. I only slightly changed the signature. This function is eventually called in other functions in the C library. double myfunc(uint n, const double* x, double* grad, void* my_func_data)Thus, as it is an Access Violation, I'm guessing the issue is with accessing elements of arrays in the D function from the C function. I don't know. When I try to call the D function in D, it works, but I have to refer to x and grad as x.ptr and grad.ptr. I'm not sure how to go about fixing this...The parameter to the C function should be declared as extern(C), and so should your function implementation. extern(C) alias FuncPtr = double function(uint, const(double)*, double*, void*); extern(C) void takeFuncPtr(FuncPtr); extern(C) double myfunc(uint n, const(double)* x, double* grad, void* my_func_data) { ... } If you haven't done that, then this is quite possibly the root of your problem.
Feb 02 2016
On Wednesday, 3 February 2016 at 00:37:25 UTC, Mike Parker wrote:The parameter to the C function should be declared as extern(C), and so should your function implementation. extern(C) alias FuncPtr = double function(uint, const(double)*, double*, void*); extern(C) void takeFuncPtr(FuncPtr); extern(C) double myfunc(uint n, const(double)* x, double* grad, void* my_func_data) { ... } If you haven't done that, then this is quite possibly the root of your problem.Success! Couldn't have done it without your help. I had originally had the equivalent of FuncPtr as extern(C), but I had removed that because myfunc wouldn't compile. I hadn't thought of putting those modifications on myfunc. Just assumed that I did the function pointers wrong. A few extra questions: 1) In other parts of the code I'm using extern(System), but that doesn't work for these. Why is extern(C) used for function pointers?, 2) You use const(double)*, in other parts of the code I had converted the C code from const char* to const(char*). Does it matter where the pointer * falls?
Feb 02 2016
On Wednesday, 3 February 2016 at 04:19:37 UTC, jmh530 wrote:A few extra questions: 1) In other parts of the code I'm using extern(System), but that doesn't work for these. Why is extern(C) used for function pointers?,extern(C) is only used with function pointers when it's needed. It depends entirely on how the C library was compiled. By default, most compilers compile with the cdecl calling convention, which is what extern(C) specifies in D code. Windows system libraries are usually compiled to use the stdcall calling convention. The D equivalent is extern(Windows). extern(System) translates to extern(Windows) on Windows and extern(C) elsewhere. Function pointers passed to C code need to have the same calling convention as that of the library to which they are passed.2) You use const(double)*, in other parts of the code I had converted the C code from const char* to const(char*). Does it matter where the pointer * falls?Technically, const(char)* is a mutable pointer to const data and const(char*) is an immutable pointer to const data.
Feb 03 2016