digitalmars.D.learn - What is the wrong with my C++ interfacing
- Ferhat =?UTF-8?B?S3VydHVsbXXFnw==?= (59/59) Mar 15 2020 The original C++ class
- drug (3/74) Mar 15 2020 What is the D version of `createSizeIntWH`? In C++ it returns a pointer
- Ferhat =?UTF-8?B?S3VydHVsbXXFnw==?= (6/10) Mar 15 2020 extern(C++){
- drug (3/16) Mar 15 2020 createSizeIntWH returns a pointer to instance, not an instance. Try:
- Ferhat =?UTF-8?B?S3VydHVsbXXFnw==?= (10/27) Mar 15 2020 I doubt it because in
- drug (2/16) Mar 15 2020 Ah, really, you use classes on D side.
- Arine (4/32) Mar 15 2020 I wouldn't use a class on the D side, unless your C++ type uses
- Ferhat =?UTF-8?B?S3VydHVsbXXFnw==?= (7/11) Mar 15 2020 I know their differences, classes are reference types and structs
- Arine (27/40) Mar 15 2020 You can, you just aren't representing the C++ code properly in D.
- Ferhat =?UTF-8?B?S3VydHVsbXXFnw==?= (7/27) Mar 16 2020 This worked for me too. But member functions are still causing
- drug (13/45) Mar 16 2020 Not tested:
- Ferhat =?UTF-8?B?S3VydHVsbXXFnw==?= (13/59) Mar 16 2020 Ok, here is a solution. I opened my lib (yielded by my auxilary
- drug (2/19) Mar 16 2020 Would be nice if you update wiki ;)
- Ferhat =?UTF-8?B?S3VydHVsbXXFnw==?= (2/22) Mar 16 2020 It would be better for someone more experienced to do this ;)
The original C++ class https://github.com/opencv/opencv/blob/master/modules/core/include/opencv2/core/types.hpp#L315: template<typename _Tp> class Size_ { public: typedef _Tp value_type; //! default constructor Size_(); Size_(_Tp _width, _Tp _height); Size_(const Size_& sz); Size_(Size_&& sz) CV_NOEXCEPT; Size_(const Point_<_Tp>& pt); Size_& operator = (const Size_& sz); Size_& operator = (Size_&& sz) CV_NOEXCEPT; //! the area (width*height) _Tp area() const; //! aspect ratio (width/height) double aspectRatio() const; //! true if empty bool empty() const; //! conversion of another data type. template<typename _Tp2> operator Size_<_Tp2>() const; _Tp width; //!< the width _Tp height; //!< the height }; // my auxiliary cpp code: cv::Size_<int>* createSizeIntWH(int _width, int _height){ return new cv::Size_<int>(_width, _height); } void deleteSizeInt(cv::Size_<int> *&sz){ delete sz; } // d code: extern(C++, cv){ class Size_(_Tp){ disable this(); final _Tp area() const; final double aspectRatio() const; final bool empty() const; _Tp width; //!< the width _Tp height; //!< the height } } // my test code that fails: Size_!int sz = createSizeIntWH(200, 100); writeln(sz.width); One of the problems is that sz.width is not printed as 200, but a random int. Other problem is that if I try to call one of area, aspectRatio, and empty, it does not compile yielding a linker error: error LNK2019: unresolved external symbol "public: int __cdecl cv::Size_<int>::area(void)const " (?area ?$Size_ H cv QEBAHXZ) referenced in function _Dmain Somehow linker cannot locate that symbol. Is this a name mangling issue? In the same library I could successfully interface cv::Mat which is a template-free definition. I suspect if D allows interfacing C++ class templates since docs do not cover this, but only struct templates?
Mar 15 2020
15.03.2020 22:39, Ferhat Kurtulmuş пишет:The original C++ class https://github.com/opencv/opencv/blob/master/modules/core/include/opencv2/ ore/types.hpp#L315: template<typename _Tp> class Size_ { public: typedef _Tp value_type; //! default constructor Size_(); Size_(_Tp _width, _Tp _height); Size_(const Size_& sz); Size_(Size_&& sz) CV_NOEXCEPT; Size_(const Point_<_Tp>& pt); Size_& operator = (const Size_& sz); Size_& operator = (Size_&& sz) CV_NOEXCEPT; //! the area (width*height) _Tp area() const; //! aspect ratio (width/height) double aspectRatio() const; //! true if empty bool empty() const; //! conversion of another data type. template<typename _Tp2> operator Size_<_Tp2>() const; _Tp width; //!< the width _Tp height; //!< the height }; // my auxiliary cpp code: cv::Size_<int>* createSizeIntWH(int _width, int _height){ return new cv::Size_<int>(_width, _height); } void deleteSizeInt(cv::Size_<int> *&sz){ delete sz; } // d code: extern(C++, cv){ class Size_(_Tp){ disable this(); final _Tp area() const; final double aspectRatio() const; final bool empty() const; _Tp width; //!< the width _Tp height; //!< the height } } // my test code that fails: Size_!int sz = createSizeIntWH(200, 100); writeln(sz.width);What is the D version of `createSizeIntWH`? In C++ it returns a pointer but in D version it returns an instance.One of the problems is that sz.width is not printed as 200, but a random int. Other problem is that if I try to call one of area, aspectRatio, and empty, it does not compile yielding a linker error: error LNK2019: unresolved external symbol "public: int __cdecl cv::Size_<int>::area(void)const " (?area ?$Size_ H cv QEBAHXZ) referenced in function _Dmain Somehow linker cannot locate that symbol. Is this a name mangling issue? In the same library I could successfully interface cv::Mat which is a template-free definition. I suspect if D allows interfacing C++ class templates since docs do not cover this, but only struct templates?
Mar 15 2020
On Sunday, 15 March 2020 at 20:21:57 UTC, drug wrote:15.03.2020 22:39, Ferhat Kurtulmuş пишет:What is the D version of `createSizeIntWH`? In C++ it returns a pointer but in D version it returns an instance.extern(C++){ cv.Size_!int createSizeInt(); cv.Size_!int createSizeIntWH(int w, int h); void deleteSizeInt(ref cv.Size_!int sz); }
Mar 15 2020
15.03.2020 23:25, Ferhat Kurtulmuş пишет:On Sunday, 15 March 2020 at 20:21:57 UTC, drug wrote:createSizeIntWH returns a pointer to instance, not an instance. Try: cv.Size_!int* createSizeIntWH(int w, int h);15.03.2020 22:39, Ferhat Kurtulmuş пишет:What is the D version of `createSizeIntWH`? In C++ it returns a pointer but in D version it returns an instance.extern(C++){ cv.Size_!int createSizeInt(); cv.Size_!int createSizeIntWH(int w, int h); void deleteSizeInt(ref cv.Size_!int sz); }
Mar 15 2020
On Sunday, 15 March 2020 at 20:46:14 UTC, drug wrote:15.03.2020 23:25, Ferhat Kurtulmuş пишет:I doubt it because in https://dlang.org/spec/cpp_interface.html#using_cpp_classes_from_d cpp code: Derived *createInstance(int i) d code: extern (C++){ ... Derived createInstance(int i); }On Sunday, 15 March 2020 at 20:21:57 UTC, drug wrote:createSizeIntWH returns a pointer to instance, not an instance. Try: cv.Size_!int* createSizeIntWH(int w, int h);15.03.2020 22:39, Ferhat Kurtulmuş пишет:What is the D version of `createSizeIntWH`? In C++ it returns a pointer but in D version it returns an instance.extern(C++){ cv.Size_!int createSizeInt(); cv.Size_!int createSizeIntWH(int w, int h); void deleteSizeInt(ref cv.Size_!int sz); }
Mar 15 2020
15.03.2020 23:53, Ferhat Kurtulmuş пишет:I doubt it because in https://dlang.org/spec/cpp_interface.html#using_cpp_classes_from_d cpp code: Derived *createInstance(int i) d code: extern (C++){ ... Derived createInstance(int i); }Ah, really, you use classes on D side.
Mar 15 2020
On Sunday, 15 March 2020 at 20:53:49 UTC, Ferhat Kurtulmuş wrote:On Sunday, 15 March 2020 at 20:46:14 UTC, drug wrote:I wouldn't use a class on the D side, unless your C++ type uses virtual functions. Classes in D are different from structs, it is not the same as C++ where they are basically the same thing.15.03.2020 23:25, Ferhat Kurtulmuş пишет:I doubt it because in https://dlang.org/spec/cpp_interface.html#using_cpp_classes_from_d cpp code: Derived *createInstance(int i) d code: extern (C++){ ... Derived createInstance(int i); }On Sunday, 15 March 2020 at 20:21:57 UTC, drug wrote:createSizeIntWH returns a pointer to instance, not an instance. Try: cv.Size_!int* createSizeIntWH(int w, int h);15.03.2020 22:39, Ferhat Kurtulmuş пишет:What is the D version of `createSizeIntWH`? In C++ it returns a pointer but in D version it returns an instance.extern(C++){ cv.Size_!int createSizeInt(); cv.Size_!int createSizeIntWH(int w, int h); void deleteSizeInt(ref cv.Size_!int sz); }
Mar 15 2020
On Sunday, 15 March 2020 at 21:16:43 UTC, Arine wrote:On Sunday, 15 March 2020 at 20:53:49 UTC, Ferhat KurtulmuşI wouldn't use a class on the D side, unless your C++ type uses virtual functions. Classes in D are different from structs, it is not the same as C++ where they are basically the same thing.I know their differences, classes are reference types and structs are value types in D. I actually don't need this code. I've already wrapped many c code, but have no so much experience with interfacing C++ code. I am trying to understand capabilities of D in interfacing with C++ and its limits. I would like to know why I can interface a template-free class, but not a class template.
Mar 15 2020
On Sunday, 15 March 2020 at 21:27:32 UTC, Ferhat Kurtulmuş wrote:On Sunday, 15 March 2020 at 21:16:43 UTC, Arine wrote:That's not the only difference. It's why your code doesn't work.On Sunday, 15 March 2020 at 20:53:49 UTC, Ferhat KurtulmuşI wouldn't use a class on the D side, unless your C++ type uses virtual functions. Classes in D are different from structs, it is not the same as C++ where they are basically the same thing.I know their differences, classes are reference types and structs are value types in D.I actually don't need this code. I've already wrapped many c code, but have no so much experience with interfacing C++ code. I am trying to understand capabilities of D in interfacing with C++ and its limits. I would like to know why I can interface a template-free class, but not a class template.You can, you just aren't representing the C++ code properly in D. You don't want class, it means something different in D than in C++. This works for me, as it is using struct that corresponds to the C++ type. You have to use extern(C++, class), as it is using "class" on the C++ side, which produces a different mangling. extern(C++, cv){ extern(C++, class) struct Size_(_Tp){ disable this(); ~this() { } final _Tp area() const; final double aspectRatio() const; final bool empty() const; _Tp width; //!< the width _Tp height; //!< the height } } extern(C++){ cv.Size_!int* createSizeIntWH(int w, int h); } void main() { Size_!int* sz = createSizeIntWH(200, 100); writeln(sz.width); }
Mar 15 2020
On Sunday, 15 March 2020 at 22:25:27 UTC, Arine wrote:On Sunday, 15 March 2020 at 21:27:32 UTC, Ferhat Kurtulmuşextern(C++, cv){ extern(C++, class) struct Size_(_Tp){ disable this(); ~this() { } final _Tp area() const; final double aspectRatio() const; final bool empty() const; _Tp width; //!< the width _Tp height; //!< the height } } extern(C++){ cv.Size_!int* createSizeIntWH(int w, int h); } void main() { Size_!int* sz = createSizeIntWH(200, 100); writeln(sz.width); }This worked for me too. But member functions are still causing linker error. It seems like docs (https://dlang.org/spec/cpp_interface.html) do not cover those situations. Is there any other sources to read for it. Maybe you make a pull request to docs covering C++ interfacing tips in detail.
Mar 16 2020
On 3/16/20 10:11 AM, Ferhat Kurtulmuş wrote:On Sunday, 15 March 2020 at 22:25:27 UTC, Arine wrote:Not tested: extern(C++, class) struct Size_(_Tp){ disable this(); ~this() { } extern(C++): // <- IIRC linkage should be set for members separately from aggregate final _Tp area() const; final double aspectRatio() const; final bool empty() const; _Tp width; //!< the width _Tp height; //!< the height }On Sunday, 15 March 2020 at 21:27:32 UTC, Ferhat Kurtulmuşextern(C++, cv){ extern(C++, class) struct Size_(_Tp){ disable this(); ~this() { } final _Tp area() const; final double aspectRatio() const; final bool empty() const; _Tp width; //!< the width _Tp height; //!< the height } } extern(C++){ cv.Size_!int* createSizeIntWH(int w, int h); } void main() { Size_!int* sz = createSizeIntWH(200, 100); writeln(sz.width); }This worked for me too. But member functions are still causing linker error. It seems like docs (https://dlang.org/spec/cpp_interface.html) do not cover those situations. Is there any other sources to read for it. Maybe you make a pull request to docs covering C++ interfacing tips in detail.
Mar 16 2020
On Monday, 16 March 2020 at 07:46:00 UTC, drug wrote:On 3/16/20 10:11 AM, Ferhat Kurtulmuş wrote:Ok, here is a solution. I opened my lib (yielded by my auxilary cpp) using 7zip. There are two files containing symbol names, 1.txt and 2.txt. I searched for names of member functions. They were not there because c++ compiler does not compile member functions of class templates because we don't actually use them. So, I simply include this line in my aux cpp file and recompiled it: template class cv::Size_<int>; I reopened 1.txt and they are there now: ?area ?$Size_ H cv QEBAHXZ ?aspectRatio ?$Size_ H cv QEBANXZ now everything works :DOn Sunday, 15 March 2020 at 22:25:27 UTC, Arine wrote:Not tested: extern(C++, class) struct Size_(_Tp){ disable this(); ~this() { } extern(C++): // <- IIRC linkage should be set for members separately from aggregate final _Tp area() const; final double aspectRatio() const; final bool empty() const; _Tp width; //!< the width _Tp height; //!< the height }On Sunday, 15 March 2020 at 21:27:32 UTC, Ferhat Kurtulmuşextern(C++, cv){ extern(C++, class) struct Size_(_Tp){ disable this(); ~this() { } final _Tp area() const; final double aspectRatio() const; final bool empty() const; _Tp width; //!< the width _Tp height; //!< the height } } extern(C++){ cv.Size_!int* createSizeIntWH(int w, int h); } void main() { Size_!int* sz = createSizeIntWH(200, 100); writeln(sz.width); }This worked for me too. But member functions are still causing linker error. It seems like docs (https://dlang.org/spec/cpp_interface.html) do not cover those situations. Is there any other sources to read for it. Maybe you make a pull request to docs covering C++ interfacing tips in detail.
Mar 16 2020
On 3/16/20 12:24 PM, Ferhat Kurtulmuş wrote:Ok, here is a solution. I opened my lib (yielded by my auxilary cpp) using 7zip. There are two files containing symbol names, 1.txt and 2.txt. I searched for names of member functions. They were not there because c++ compiler does not compile member functions of class templates because we don't actually use them. So, I simply include this line in my aux cpp file and recompiled it: template class cv::Size_<int>; I reopened 1.txt and they are there now: ?area ?$Size_ H cv QEBAHXZ ?aspectRatio ?$Size_ H cv QEBANXZ now everything works :DWould be nice if you update wiki ;)
Mar 16 2020
On Monday, 16 March 2020 at 09:28:15 UTC, drug wrote:On 3/16/20 12:24 PM, Ferhat Kurtulmuş wrote:It would be better for someone more experienced to do this ;)Ok, here is a solution. I opened my lib (yielded by my auxilary cpp) using 7zip. There are two files containing symbol names, 1.txt and 2.txt. I searched for names of member functions. They were not there because c++ compiler does not compile member functions of class templates because we don't actually use them. So, I simply include this line in my aux cpp file and recompiled it: template class cv::Size_<int>; I reopened 1.txt and they are there now: ?area ?$Size_ H cv QEBAHXZ ?aspectRatio ?$Size_ H cv QEBANXZ now everything works :DWould be nice if you update wiki ;)
Mar 16 2020