www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - C++ Interfacing:'static' array function parameter contradiction

reply ParticlePeter <ParticlePeter gmx.de> writes:
C++ Function:
bool cppFunc( float[3] color );

D binding:
extern(C++) bool cppFunc( float[3] color );

Using with:
float[3] my_color;
cppFunc( my_color );

-> Error: Internal Compiler Error: unable to pass static array to 
extern(C++) function.
Error: Use pointer instead.


Using with:
cppFunc( my_color.ptr );

-> Error: function cppFunc( float[3] color ) is not callable 
using argument types (float*)


Altering D binding:
extern(C++) bool cppFunc( float* color );

Using with:
cppFunc( my_color.ptr );

-> error LNK2001: unresolved external symbol "bool __cdecl 
cppFunc(float *)" Binding.exe : fatal error LNK1120: 1 unresolved 
externals
Error: linker exited with status 1120
dmd failed with exit code 1120.


So what next? How can I interface to the cpp function?
Apr 28 2017
next sibling parent Kagamin <spam here.lot> writes:
Report a bug.
Apr 28 2017
prev sibling next sibling parent reply kinke <noone nowhere.com> writes:
On Friday, 28 April 2017 at 15:56:17 UTC, ParticlePeter wrote:
 So what next? How can I interface to the cpp function?
*** C++: bool cppFunc(float (&color)[3]) { color[0] = 1; color[1] = 2; color[2] = 3; return true; } *** D: extern(C++) bool cppFunc(ref float[3] color); void main() { float[3] my_color; cppFunc(my_color); assert(my_color == [ 1, 2, 3 ]); }
Apr 28 2017
parent ParticlePeter <ParticlePeter gmx.de> writes:
On Friday, 28 April 2017 at 17:15:54 UTC, kinke wrote:
 On Friday, 28 April 2017 at 15:56:17 UTC, ParticlePeter wrote:
 So what next? How can I interface to the cpp function?
*** C++: bool cppFunc(float (&color)[3]) { color[0] = 1; color[1] = 2; color[2] = 3; return true; } *** D: extern(C++) bool cppFunc(ref float[3] color); void main() { float[3] my_color; cppFunc(my_color); assert(my_color == [ 1, 2, 3 ]); }
The c++ lib is not mine and your answer implies extra work on the c++ from my side. Possible, but not desired, I think calling my original c++ function should interface with an d pointer. That being said, I think Kagamin is right.
Apr 28 2017
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 04/28/2017 08:56 AM, ParticlePeter wrote:
 C++ Function:
 bool cppFunc( float[3] color );

 D binding:
 extern(C++) bool cppFunc( float[3] color );

 Using with:
 float[3] my_color;
 cppFunc( my_color );

 -> Error: Internal Compiler Error: unable to pass static array to
That part is a bug at least in the compiler message. Is it really an internal ctompiler error? Doesn't look like it: the compiler is talking to us happily. :) My simple test works for me: // deneme.cpp float cppFunc(float color[3]) { return color[0] + color[1] + color[2]; } $ g++ -c deneme.cpp -o deneme_cpp.o // deneme.d extern(C++) float cppFunc(float * color); void main() { float[3] my_color = [ 1.5, 2.5, 3.5 ] ; assert(cppFunc(my_color.ptr) == 7.5); } $ dmd deneme_cpp.o deneme.d -of=deneme Builds and runs fine... on Linux... I don't know whether that's significant. Ali
Apr 28 2017
next sibling parent reply ParticlePeter <ParticlePeter gmx.de> writes:
On Friday, 28 April 2017 at 17:57:34 UTC, Ali Çehreli wrote:
 On 04/28/2017 08:56 AM, ParticlePeter wrote:
 C++ Function:
 bool cppFunc( float[3] color );

 D binding:
 extern(C++) bool cppFunc( float[3] color );

 Using with:
 float[3] my_color;
 cppFunc( my_color );

 -> Error: Internal Compiler Error: unable to pass static
array to That part is a bug at least in the compiler message. Is it really an internal ctompiler error? Doesn't look like it: the compiler is talking to us happily. :) My simple test works for me: // deneme.cpp float cppFunc(float color[3]) { return color[0] + color[1] + color[2]; } $ g++ -c deneme.cpp -o deneme_cpp.o // deneme.d extern(C++) float cppFunc(float * color); void main() { float[3] my_color = [ 1.5, 2.5, 3.5 ] ; assert(cppFunc(my_color.ptr) == 7.5); } $ dmd deneme_cpp.o deneme.d -of=deneme Builds and runs fine... on Linux... I don't know whether that's significant. Ali
Interesting, your example corresponds to my third case, the linker error. I am on Window, building an x64 App, afaik in that case the MS Visual Studio linker is used instead of optilink. Will add your findings to the bug report.
Apr 28 2017
parent reply kinke <noone nowhere.com> writes:
On Friday, 28 April 2017 at 18:07:49 UTC, ParticlePeter wrote:
 Interesting, your example corresponds to my third case, the 
 linker error. I am on Window, building an x64 App, afaik in 
 that case the MS Visual Studio linker is used instead of 
 optilink. Will add your findings to the bug report.
Apparently Microsoft's C++ compiler doesn't mangle `float arg[3]` parameters identically to `float* arg`: void cppSArray(float color[3]) => ?cppSArray YAXQEAM Z void cppPtr(float* color) => ?cppPtr YAXPEAM Z
Apr 28 2017
parent reply Atila Neves <atila.neves gmail.com> writes:
On Friday, 28 April 2017 at 18:41:22 UTC, kinke wrote:
 On Friday, 28 April 2017 at 18:07:49 UTC, ParticlePeter wrote:
 Interesting, your example corresponds to my third case, the 
 linker error. I am on Window, building an x64 App, afaik in 
 that case the MS Visual Studio linker is used instead of 
 optilink. Will add your findings to the bug report.
Apparently Microsoft's C++ compiler doesn't mangle `float arg[3]` parameters identically to `float* arg`: void cppSArray(float color[3]) => ?cppSArray YAXQEAM Z void cppPtr(float* color) => ?cppPtr YAXPEAM Z
The worst part about that is mangling aside, the two declarations are identical to the compiler. Atila
Apr 28 2017
parent reply ParticlePeter <ParticlePeter gmx.de> writes:
On Saturday, 29 April 2017 at 01:49:56 UTC, Atila Neves wrote:
 On Friday, 28 April 2017 at 18:41:22 UTC, kinke wrote:
 On Friday, 28 April 2017 at 18:07:49 UTC, ParticlePeter wrote:
 Interesting, your example corresponds to my third case, the 
 linker error. I am on Window, building an x64 App, afaik in 
 that case the MS Visual Studio linker is used instead of 
 optilink. Will add your findings to the bug report.
Apparently Microsoft's C++ compiler doesn't mangle `float arg[3]` parameters identically to `float* arg`: void cppSArray(float color[3]) => ?cppSArray YAXQEAM Z void cppPtr(float* color) => ?cppPtr YAXPEAM Z
The worst part about that is mangling aside, the two declarations are identical to the compiler. Atila
In this context, can anybody explain [1], in particular, in this case, one should extern( C++ ) void cppSArray( ref float[3] color ); instead of: extern( C++ ) void cppSArray( float* color ); Others and me in this discussion seem to agree that parameter (float color[3]) is equivalent to (float* color) in C++ world. [1] http://dlang.org/spec/interfaceToC.html#passing_d_array
Apr 28 2017
parent reply Atila Neves <atila.neves gmail.com> writes:
On Saturday, 29 April 2017 at 06:22:03 UTC, ParticlePeter wrote:
 On Saturday, 29 April 2017 at 01:49:56 UTC, Atila Neves wrote:
 On Friday, 28 April 2017 at 18:41:22 UTC, kinke wrote:
 [...]
The worst part about that is mangling aside, the two declarations are identical to the compiler. Atila
In this context, can anybody explain [1], in particular, in this case, one should extern( C++ ) void cppSArray( ref float[3] color ); instead of: extern( C++ ) void cppSArray( float* color ); Others and me in this discussion seem to agree that parameter (float color[3]) is equivalent to (float* color) in C++ world. [1] http://dlang.org/spec/interfaceToC.html#passing_d_array
It's "just" the mangling. If it were `extern(C)` there'd be nothing to talk about. Atila
Apr 29 2017
parent ParticlePeter <ParticlePeter gmx.de> writes:
On Saturday, 29 April 2017 at 10:17:47 UTC, Atila Neves wrote:
 On Saturday, 29 April 2017 at 06:22:03 UTC, ParticlePeter wrote:
 On Saturday, 29 April 2017 at 01:49:56 UTC, Atila Neves wrote:
 On Friday, 28 April 2017 at 18:41:22 UTC, kinke wrote:
 [...]
The worst part about that is mangling aside, the two declarations are identical to the compiler. Atila
In this context, can anybody explain [1], in particular, in this case, one should extern( C++ ) void cppSArray( ref float[3] color ); instead of: extern( C++ ) void cppSArray( float* color ); Others and me in this discussion seem to agree that parameter (float color[3]) is equivalent to (float* color) in C++ world. [1] http://dlang.org/spec/interfaceToC.html#passing_d_array
It's "just" the mangling. If it were `extern(C)` there'd be nothing to talk about. Atila
O.k. got it, so both D variants work with the same C++ mangling, thanks.
Apr 29 2017
prev sibling parent reply ParticlePeter <ParticlePeter gmx.de> writes:
On Friday, 28 April 2017 at 17:57:34 UTC, Ali Çehreli wrote:
 On 04/28/2017 08:56 AM, ParticlePeter wrote:
 C++ Function:
 bool cppFunc( float[3] color );

 D binding:
 extern(C++) bool cppFunc( float[3] color );

 Using with:
 float[3] my_color;
 cppFunc( my_color );

 -> Error: Internal Compiler Error: unable to pass static
array to That part is a bug at least in the compiler message. Is it really an internal ctompiler error? Doesn't look like it: the compiler is talking to us happily. :) My simple test works for me: // deneme.cpp float cppFunc(float color[3]) { return color[0] + color[1] + color[2]; } $ g++ -c deneme.cpp -o deneme_cpp.o // deneme.d extern(C++) float cppFunc(float * color); void main() { float[3] my_color = [ 1.5, 2.5, 3.5 ] ; assert(cppFunc(my_color.ptr) == 7.5); } $ dmd deneme_cpp.o deneme.d -of=deneme Builds and runs fine... on Linux... I don't know whether that's significant. Ali
Btw, according to [1] your example should not work either, I doubt that there is a difference between C and C++ interfacing, it should be: extern(C++) float cppFunc( ref float[3] color ); In my case its a linker error as well. [1] http://dlang.org/spec/interfaceToC.html#passing_d_array
Apr 28 2017
parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Friday, 28 April 2017 at 19:08:18 UTC, ParticlePeter wrote:
 On Friday, 28 April 2017 at 17:57:34 UTC, Ali Çehreli wrote:
 On 04/28/2017 08:56 AM, ParticlePeter wrote:
 C++ Function:
 bool cppFunc( float[3] color );

 D binding:
 extern(C++) bool cppFunc( float[3] color );

 Using with:
 float[3] my_color;
 cppFunc( my_color );

 -> Error: Internal Compiler Error: unable to pass static
array to That part is a bug at least in the compiler message. Is it really an internal ctompiler error? Doesn't look like it: the compiler is talking to us happily. :) My simple test works for me: // deneme.cpp float cppFunc(float color[3]) { return color[0] + color[1] + color[2]; } $ g++ -c deneme.cpp -o deneme_cpp.o // deneme.d extern(C++) float cppFunc(float * color); void main() { float[3] my_color = [ 1.5, 2.5, 3.5 ] ; assert(cppFunc(my_color.ptr) == 7.5); } $ dmd deneme_cpp.o deneme.d -of=deneme Builds and runs fine... on Linux... I don't know whether that's significant. Ali
Btw, according to [1] your example should not work either, I doubt that there is a difference between C and C++ interfacing, it should be: extern(C++) float cppFunc( ref float[3] color ); In my case its a linker error as well. [1] http://dlang.org/spec/interfaceToC.html#passing_d_array
If you are having problems with the linker with Ali's you can do ``` extern(C++) bool cppFunc( float[3] color ); // correct signature, but causes compiler error pragma(mangle, cppFunc.mangleof) float cppFunc(float * color); // compatible signature but wrong mangling overridden with pragma(mangle,...)
Apr 28 2017
parent reply ParticlePeter <ParticlePeter gmx.de> writes:
On Saturday, 29 April 2017 at 00:31:32 UTC, Nicholas Wilson wrote:
 If you are having problems with the linker with Ali's you can do
 ```
 extern(C++) bool cppFunc( float[3] color ); // correct 
 signature, but causes compiler error

 pragma(mangle, cppFunc.mangleof)
 float cppFunc(float * color); // compatible signature but wrong 
 mangling overridden with pragma(mangle,...)
Thanks for that hint! I got it to work. Side note, cppFunc.mangleof cannot be used as it is unknown. I guess your intention was to get the C++ mangling from somewhere else, I got it from dependency walker.
Apr 29 2017
parent reply =?UTF-8?B?2LPZhNmK2YXYp9mGINin2YTYs9mH?= writes:
On Saturday, 29 April 2017 at 08:08:27 UTC, ParticlePeter wrote:
 On Saturday, 29 April 2017 at 00:31:32 UTC, Nicholas Wilson 
 wrote:
 If you are having problems with the linker with Ali's you can 
 do
 ```
 extern(C++) bool cppFunc( float[3] color ); // correct 
 signature, but causes compiler error

 pragma(mangle, cppFunc.mangleof)
 float cppFunc(float * color); // compatible signature but 
 wrong mangling overridden with pragma(mangle,...)
Thanks for that hint! I got it to work. Side note, cppFunc.mangleof cannot be used as it is unknown. I guess your intention was to get the C++ mangling from somewhere else, I got it from dependency walker.
But still, this needs to be fixed, copy pasting the name mangling is in my opinion just a hack for your specific cpp compiler on your specific platform.
Apr 29 2017
parent kinke <noone nowhere.com> writes:
On Saturday, 29 April 2017 at 18:54:36 UTC, سليمان السهمي 
(Soulaïman Sahmi) wrote:
 But still, this needs to be fixed, copy pasting the name 
 mangling is in my opinion just a hack for your specific cpp 
 compiler on your specific platform.
It can't be fixed on the D side as the Visual C++ mangling of `float color[3]` as `float * const color` cannot be represented in D, see the corresponding DMD issue https://issues.dlang.org/show_bug.cgi?id=17359. Just to be clear, a D declaration `extern(C++) bool cppFunc(float[3] color)` isn't compatible with the nearly identically looking C++ one, as it implies by-value semantics for `color` (not available in C++), that's why DMD doesn't allow it and so can't mangle it according to the target's C++ compiler. And the C++ byref version `float (&color)[3]` is mangled differently again (compatible with D's `ref float[3]`).
Apr 29 2017