digitalmars.D.learn - Passing pointer to extern(C++) templated function
- Jamie (72/72) Oct 13 2020 I'm having difficulties linking templated functions with multiple
- James Blachly (3/16) Oct 13 2020 Is the template even instantiated? With just a template definition and
- =?UTF-8?Q?Ali_=c3=87ehreli?= (6/23) Oct 13 2020 Yes, they all have explicit template instantiations on the C++ side.
- Jamie (7/13) Oct 13 2020 Why would the 'turtles all the way down' change function
- kinke (7/9) Oct 13 2020 Nope, it's a bug in the Itanium C++ mangler, please file a bug.
I'm having difficulties linking templated functions with multiple pointer arguments with extern(C++). a.cpp ----- template<typename T> void func1(T *b){} template void func1<int>(int *b); template<typename T> void func2(const T *a){} template void func2<int>(const int *a); template<typename T> void func3(T *b, const T *a){} template void func3<int>(int *b, const int *a); template<typename T> void func4(const T *a, T *b){} template void func4<int>(const int *a, int *b); void func5(int *b, const int *a){} void func6(const int *a, int *b){}; ----- main.d ----- extern (C++) { void func1(T)(T *b); void func2(T)(const T *a); void func3(T)(T *b, const T *a); void func4(T)(const T *a, T *b); void func5(int *b, const int *a); void func6(const int *a, int *b); } void main() { int i = 4; int *pi = &i; func1(pi); func2(&i); func3(pi, &i); func4(&i, pi); func5(pi, &i); func6(&i, pi); } ----- Building with: g++ -c a.cpp dmd main.d a.o Throws the error: /usr/bin/ld: main.o: in function `_Dmain': main.d:(.text._Dmain[_Dmain]+0x31): undefined reference to `void func3<int>(int*, int*)' /usr/bin/ld: main.d:(.text._Dmain[_Dmain]+0x3e): undefined reference to `void func4<int>(int const*, int const)' collect2: error: ld returned 1 exit status Error: linker exited with status 1 When I inspect the object files, I see the following: a.o ----- void func1<int>(int*) void func2<int>(int const*) void func3<int>(int*, int const*) void func4<int>(int const*, int*) func5(int*, int const*) func6(int const*, int*) ----- main.o ----- void func1<int>(int*) void func2<int>(int const*) void func3<int>(int*, int*) void func4<int>(int const*, int const) func5(int*, int const*) func6(int const*, int*) ----- It appears that func3 and func4 take on different types depending on other variables being present? Is this expected? Why do they differ from the non-templated functions func5 and func6 respectively? How should I achieve this instead?
Oct 13 2020
On 10/13/20 5:23 AM, Jamie wrote:Building with: g++ -c a.cpp dmd main.d a.o Throws the error: /usr/bin/ld: main.o: in function `_Dmain': main.d:(.text._Dmain[_Dmain]+0x31): undefined reference to `void func3<int>(int*, int*)' /usr/bin/ld: main.d:(.text._Dmain[_Dmain]+0x3e): undefined reference to `void func4<int>(int const*, int const)' collect2: error: ld returned 1 exit status Error: linker exited with status 1Is the template even instantiated? With just a template definition and an object file I am surprised you even have a symbol?
Oct 13 2020
On 10/13/20 4:11 PM, James Blachly wrote:On 10/13/20 5:23 AM, Jamie wrote:Yes, they all have explicit template instantiations on the C++ side. I think the issue is with D's "turtles all the way down" style const. My workaround would be to define wrapper functions that may need to do casting on one or the other side. AliBuilding with: g++ -c a.cpp dmd main.d a.o Throws the error: /usr/bin/ld: main.o: in function `_Dmain': main.d:(.text._Dmain[_Dmain]+0x31): undefined reference to `void func3<int>(int*, int*)' /usr/bin/ld: main.d:(.text._Dmain[_Dmain]+0x3e): undefined reference to `void func4<int>(int const*, int const)' collect2: error: ld returned 1 exit status Error: linker exited with status 1Is the template even instantiated? With just a template definition and an object file I am surprised you even have a symbol?
Oct 13 2020
On Tuesday, 13 October 2020 at 23:39:38 UTC, Ali Çehreli wrote:On 10/13/20 4:11 PM, James Blachly wrote:Why would the 'turtles all the way down' change function arguments? They are on the same 'level' whereas I took the transitive const to be applied through different depths in functions / classes etc. Thanks for the suggestion, my current work around is to just remove the const but casting sounds a bit safer.On 10/13/20 5:23 AM, Jamie wrote:I think the issue is with D's "turtles all the way down" style const. My workaround would be to define wrapper functions that may need to do casting on one or the other side. Ali
Oct 13 2020
On Tuesday, 13 October 2020 at 09:23:48 UTC, Jamie wrote:It appears that func3 and func4 take on different types depending on other variables being present? Is this expected?Nope, it's a bug in the Itanium C++ mangler, please file a bug. MSVC++ mangling seems fine, after fixing the D declarations to void func3(T)(T* b, const(T)* a); void func4(T)(const(T)* a, T* b); [A D `const T*` is equivalent to C++ `const T* const`; this matters for MSVC mangling...].
Oct 13 2020
On Tuesday, 13 October 2020 at 23:47:24 UTC, kinke wrote:On Tuesday, 13 October 2020 at 09:23:48 UTC, Jamie wrote:Happy to file a bug, but if it was a bug in the mangler wouldn't both C++ and D get the same result? Assuming D uses the same mangler for the extern(C++) stuff.It appears that func3 and func4 take on different types depending on other variables being present? Is this expected?Nope, it's a bug in the Itanium C++ mangler, please file a bug. MSVC++ mangling seems fine, after fixing the D declarations to void func3(T)(T* b, const(T)* a); void func4(T)(const(T)* a, T* b); [A D `const T*` is equivalent to C++ `const T* const`; this matters for MSVC mangling...].
Oct 13 2020
On Wednesday, 14 October 2020 at 00:25:56 UTC, Jamie wrote:Happy to file a bug, but if it was a bug in the mangler wouldn't both C++ and D get the same result? Assuming D uses the same mangler for the extern(C++) stuff.Bug in the D frontend implementation of Itanium C++ mangling. https://github.com/dlang/dmd/blob/master/src/dmd/cppmangle.d
Oct 13 2020