Jump to page: 1 2
Thread overview
What is the wrong with my C++ interfacing
Mar 15, 2020
Ferhat Kurtulmuş
Mar 15, 2020
drug
Mar 15, 2020
Ferhat Kurtulmuş
Mar 15, 2020
drug
Mar 15, 2020
Ferhat Kurtulmuş
Mar 15, 2020
drug
Mar 15, 2020
Arine
Mar 15, 2020
Ferhat Kurtulmuş
Mar 15, 2020
Arine
Mar 16, 2020
Ferhat Kurtulmuş
Mar 16, 2020
drug
Mar 16, 2020
Ferhat Kurtulmuş
Mar 16, 2020
drug
Mar 16, 2020
Ferhat Kurtulmuş
March 15, 2020
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?

March 15, 2020
15.03.2020 22:39, Ferhat Kurtulmuş пишет:
> 
> 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);

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?
> 
March 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);
}

March 15, 2020
15.03.2020 23:25, Ferhat Kurtulmuş пишет:
> 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);
> }
> 

createSizeIntWH returns a pointer to instance, not an instance. Try:
cv.Size_!int* createSizeIntWH(int w, int h);
March 15, 2020
On Sunday, 15 March 2020 at 20:46:14 UTC, drug wrote:
> 15.03.2020 23:25, Ferhat Kurtulmuş пишет:
>> 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);
>> }
>> 
>
> createSizeIntWH returns a pointer to instance, not an instance. Try:
> cv.Size_!int* createSizeIntWH(int w, int h);

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);
}


March 16, 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.


March 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:
>> 15.03.2020 23:25, Ferhat Kurtulmuş пишет:
>>> 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);
>>> }
>>> 
>>
>> createSizeIntWH returns a pointer to instance, not an instance. Try:
>> cv.Size_!int* createSizeIntWH(int w, int h);
>
> 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);
> }

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.
March 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.
March 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:
>> 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.

That's not the only difference. It's why your code doesn't work.

> 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);
}

March 16, 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.
« First   ‹ Prev
1 2