D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 17359 - C++ Interfacing: function with 'static' array parameter cannot be linked (x64)
Summary: C++ Interfacing: function with 'static' array parameter cannot be linked (x64)
Status: RESOLVED WORKSFORME
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: x86_64 Windows
: P1 blocker
Assignee: No Owner
URL:
Keywords: C++, mangling
Depends on:
Blocks:
 
Reported: 2017-04-28 19:41 UTC by Peter Particle
Modified: 2022-03-01 02:04 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Peter Particle 2017-04-28 19:41:26 UTC
C++ Interfacing: function with 'static' array parameter cannot be linked (x64)

C++ prototype:
bool cppFunc( float[3] color );

D binding (as described here [1])
extern(C++) bool cppFunc( ref float color );

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

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

Same problem but slightly different error messages with LDC. 

The issue is discussed here in additional detail [2].

Summary:
Ali mentions that following variant works for him on linux:
"
// 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
"
Comment:
This varinat leads to the same compiler error (with "bool __cdecl cppFunc(float*)" message) on windows compiled for x64.


kinke points out:
" 
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
"

This contradicts Alis variant but not the 'ref' variant. But I belief that the 'ref' variant is also a mangling problem.


[1] http://dlang.org/spec/interfaceToC.html#passing_d_array
[2] https://forum.dlang.org/post/qcmrdrebuuhjfendyzud@forum.dlang.org
Comment 1 Peter Particle 2017-04-29 07:52:36 UTC
As a work around, we can use Ali's variant and pragma(mangle, "mangle_string"). I found my "mangle_string" with dependency walker.
Comment 2 kinke 2017-04-29 09:39:03 UTC
I think this is no DMD bug. The problem is that Microsoft unlike gcc mangles the `float color[3]` variant as `float * const color`, which can't be represented in D directly (const pointer to mutable data).
Comment 3 kinke 2017-04-29 09:57:19 UTC
So the proper workaround for MSVC targets would be:

C++:

bool cppFunc(float color[3])
{
    for (int i = 0; i < 3; ++i) color[i] *= 2;
    return true;
}

D:

pragma(mangle, "?cppFunc@@YA_NQEAM@Z")
extern(C++) bool cppFunc(ref float[3] color);

void main()
{
    float[3] my_color = [ 1, 2, 3 ];
    cppFunc(my_color);
    assert(my_color == [ 2, 4, 6 ]);
}
Comment 4 Walter Bright 2018-04-10 05:38:03 UTC
To get the same results in C++ and D:

C++:
  void cppFunc(float (&color)[3]) { }

D:
  extern(C++) void cppFunc(ref float[3] color) { }

Both mangle to:
  ?cppFunc@@YAXAAY02M@Z