www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Passing pointer to extern(C++) templated function

reply Jamie <email gmail.com> writes:
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
next sibling parent reply James Blachly <james.blachly gmail.com> writes:
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 1
 
Is the template even instantiated? With just a template definition and an object file I am surprised you even have a symbol?
Oct 13 2020
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 10/13/20 4:11 PM, James Blachly wrote:
 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 1
Is the template even instantiated? With just a template definition and an object file I am surprised you even have a symbol?
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. Ali
Oct 13 2020
parent Jamie <email gmail.com> writes:
On Tuesday, 13 October 2020 at 23:39:38 UTC, Ali Çehreli wrote:
 On 10/13/20 4:11 PM, James Blachly wrote:
 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
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.
Oct 13 2020
prev sibling parent reply kinke <noone nowhere.com> writes:
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
parent reply Jamie <email gmail.com> writes:
On Tuesday, 13 October 2020 at 23:47:24 UTC, kinke wrote:
 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...].
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.
Oct 13 2020
parent kinke <noone nowhere.com> writes:
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