www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - C++ interface problem

reply "extrawurst" <stephan extrawurst.org> writes:
I hope someone can tell me where my bug is.
I am linking to a dynamic library with C++ interfaces:

```
//alias S = ulong;
struct S
{
   ulong data;
}

extern(C) I getI();

extern(C++) interface I
{
   void foo();
   S bar();
}
```

now the question is why does it crash to access bar() in both 
cases? (using alias aswell as the struct)
The C++ class S is a POD class (it contains only 64bits of data 
and is compiled byte aligned)
The call to bar() from D just crashes on win32, the interface 
works fine on osx 64bit.
Any help would be welcome! Is this even possible to solve ? I 
have no access to the library code so I am not able to build the 
C++ lib with like DMC or something...
Apr 26 2015
parent reply "Laeeth Isharc" <Laeeth.nospam nospam-laeeth.com> writes:
On Sunday, 26 April 2015 at 15:49:46 UTC, extrawurst wrote:
 I hope someone can tell me where my bug is.
 I am linking to a dynamic library with C++ interfaces:

 ```
 //alias S = ulong;
 struct S
 {
   ulong data;
 }

 extern(C) I getI();

 extern(C++) interface I
 {
   void foo();
   S bar();
 }
 ```

 now the question is why does it crash to access bar() in both 
 cases? (using alias aswell as the struct)
 The C++ class S is a POD class (it contains only 64bits of data 
 and is compiled byte aligned)
 The call to bar() from D just crashes on win32, the interface 
 works fine on osx 64bit.
 Any help would be welcome! Is this even possible to solve ? I 
 have no access to the library code so I am not able to build 
 the C++ lib with like DMC or something...
Long always 64 bit in D but varies with architecture in C. See here: http://wiki.dlang.org/Converting_C_.h_Files_to_D_Modules Core.stdc.config has alias for the C type that you can use in place of long.
Apr 27 2015
parent reply "extrawurst" <stephan extrawurst.org> writes:
On Monday, 27 April 2015 at 07:37:23 UTC, Laeeth Isharc wrote:
 On Sunday, 26 April 2015 at 15:49:46 UTC, extrawurst wrote:
 I hope someone can tell me where my bug is.
 I am linking to a dynamic library with C++ interfaces:

 ```
 //alias S = ulong;
 struct S
 {
  ulong data;
 }

 extern(C) I getI();

 extern(C++) interface I
 {
  void foo();
  S bar();
 }
 ```

 now the question is why does it crash to access bar() in both 
 cases? (using alias aswell as the struct)
 The C++ class S is a POD class (it contains only 64bits of 
 data and is compiled byte aligned)
 The call to bar() from D just crashes on win32, the interface 
 works fine on osx 64bit.
 Any help would be welcome! Is this even possible to solve ? I 
 have no access to the library code so I am not able to build 
 the C++ lib with like DMC or something...
Long always 64 bit in D but varies with architecture in C. See here: http://wiki.dlang.org/Converting_C_.h_Files_to_D_Modules Core.stdc.config has alias for the C type that you can use in place of long.
Thought about that too and tried uint aswell. does not work either..
Apr 27 2015
parent reply "Benjamin Thaut" <code benjamin-thaut.de> writes:
On Monday, 27 April 2015 at 11:00:23 UTC, extrawurst wrote:
 Thought about that too and tried uint aswell. does not work 
 either..
Please post the c++ declarations as well. Which c++ compiler do you use for win32? (dmc or msvc) Kind Regards Benjamin
Apr 27 2015
parent reply "extrawurst" <stephan extrawurst.org> writes:
On Monday, 27 April 2015 at 12:56:57 UTC, Benjamin Thaut wrote:
 On Monday, 27 April 2015 at 11:00:23 UTC, extrawurst wrote:
 Thought about that too and tried uint aswell. does not work 
 either..
Please post the c++ declarations as well. Which c++ compiler do you use for win32? (dmc or msvc) Kind Regards Benjamin
Don't ask me about the compiler, like stated above I have no control over the binaries, it is proprietary. the C++ class basically is: ``` class S { union SteamID_t { struct SteamIDComponent_t { uint32 m_unAccountID : 32; unsigned int m_unAccountInstance : 20; unsigned int m_EAccountType : 4; EUniverse m_EUniverse : 8; } m_comp; uint64 m_unAll64Bits; } m_steamid; } ```
Apr 27 2015
parent reply "Benjamin Thaut" <code benjamin-thaut.de> writes:
On Monday, 27 April 2015 at 13:08:33 UTC, extrawurst wrote:
 Don't ask me about the compiler, like stated above I have no 
 control over the binaries, it is proprietary.
Thats bad to start with.
 the C++ class basically is:

 ```
 class S
 {
 union SteamID_t
 	{
 		struct SteamIDComponent_t
 		{
 			uint32				m_unAccountID : 32;
 			unsigned int		m_unAccountInstance : 20;
 			unsigned int		m_EAccountType : 4;
 			EUniverse			m_EUniverse : 8;
 		} m_comp;

 		uint64 m_unAll64Bits;
 	} m_steamid;
 }
 ```
Where is the fuction declaratiosn for bar? If bar is not virtual you can not use a extern(C++) Interface. If bar is non-virtual you have to use a extern(C++) class.
Apr 27 2015
parent reply "extrawurst" <stephan extrawurst.org> writes:
On Monday, 27 April 2015 at 13:14:21 UTC, Benjamin Thaut wrote:
 On Monday, 27 April 2015 at 13:08:33 UTC, extrawurst wrote:
 Don't ask me about the compiler, like stated above I have no 
 control over the binaries, it is proprietary.
Thats bad to start with.
 the C++ class basically is:

 ```
 class S
 {
 union SteamID_t
 	{
 		struct SteamIDComponent_t
 		{
 			uint32				m_unAccountID : 32;
 			unsigned int		m_unAccountInstance : 20;
 			unsigned int		m_EAccountType : 4;
 			EUniverse			m_EUniverse : 8;
 		} m_comp;

 		uint64 m_unAll64Bits;
 	} m_steamid;
 }
 ```
Where is the fuction declaratiosn for bar? If bar is not virtual you can not use a extern(C++) Interface. If bar is non-virtual you have to use a extern(C++) class.
of course it is all virtual. it is a c++-interface. and everything works fine under osx, that would not be the case otherwise, right ?
Apr 27 2015
parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 27.04.2015 um 17:16 schrieb extrawurst:
 On Monday, 27 April 2015 at 13:14:21 UTC, Benjamin Thaut wrote:
 On Monday, 27 April 2015 at 13:08:33 UTC, extrawurst wrote:
 Don't ask me about the compiler, like stated above I have no control
 over the binaries, it is proprietary.
Thats bad to start with.
 the C++ class basically is:

 ```
 class S
 {
 union SteamID_t
     {
         struct SteamIDComponent_t
         {
             uint32                m_unAccountID : 32;
             unsigned int        m_unAccountInstance : 20;
             unsigned int        m_EAccountType : 4;
             EUniverse            m_EUniverse : 8;
         } m_comp;

         uint64 m_unAll64Bits;
     } m_steamid;
 }
 ```
Where is the fuction declaratiosn for bar? If bar is not virtual you can not use a extern(C++) Interface. If bar is non-virtual you have to use a extern(C++) class.
of course it is all virtual. it is a c++-interface. and everything works fine under osx, that would not be the case otherwise, right ?
It depends on the compiler, I don't know the vtbl layout on OSX. Does the class have a virtual destructor? If you would post a bit more of S declaration I wouldn't have to guess into the blue. Not knowing the compiler your third party library was compiled with doesn't really help either. Kind Regards Benjamin
Apr 27 2015
parent reply "extrawurst" <stephan extrawurst.org> writes:
On Monday, 27 April 2015 at 16:24:16 UTC, Benjamin Thaut wrote:
 Am 27.04.2015 um 17:16 schrieb extrawurst:
 On Monday, 27 April 2015 at 13:14:21 UTC, Benjamin Thaut wrote:
 On Monday, 27 April 2015 at 13:08:33 UTC, extrawurst wrote:
 Don't ask me about the compiler, like stated above I have no 
 control
 over the binaries, it is proprietary.
Thats bad to start with.
 the C++ class basically is:

 ```
 class S
 {
 union SteamID_t
    {
        struct SteamIDComponent_t
        {
            uint32                m_unAccountID : 32;
            unsigned int        m_unAccountInstance : 20;
            unsigned int        m_EAccountType : 4;
            EUniverse            m_EUniverse : 8;
        } m_comp;

        uint64 m_unAll64Bits;
    } m_steamid;
 }
 ```
Where is the fuction declaratiosn for bar? If bar is not virtual you can not use a extern(C++) Interface. If bar is non-virtual you have to use a extern(C++) class.
of course it is all virtual. it is a c++-interface. and everything works fine under osx, that would not be the case otherwise, right ?
It depends on the compiler, I don't know the vtbl layout on OSX. Does the class have a virtual destructor? If you would post a bit more of S declaration I wouldn't have to guess into the blue. Not knowing the compiler your third party library was compiled with doesn't really help either. Kind Regards Benjamin
here is the shortened version of the returned class CSteamID: https://gist.github.com/Extrawurst/936f56ceaa87cf287257 this is the shortened interface (no destructors in the rest of the code either): https://gist.github.com/Extrawurst/b20dc5ab84132ecab30d the method `GetFriendByIndex` is the one crashing on win32.
Apr 27 2015
parent reply "Benjamin Thaut" <code benjamin-thaut.de> writes:
On Monday, 27 April 2015 at 21:19:02 UTC, extrawurst wrote:
 here is the shortened version of the returned class CSteamID:
 https://gist.github.com/Extrawurst/936f56ceaa87cf287257

 this is the shortened interface (no destructors in the rest of 
 the code either):
 https://gist.github.com/Extrawurst/b20dc5ab84132ecab30d

 the method `GetFriendByIndex` is the one crashing on win32.
I assume that's because CSteamID is returned by value. Are you defining CSteamID in D as a struct? If not you have to because only structs can be returned by value. The next problem is that CSteamID is 64bits wide, this might be a problem as it can not be returned in a single register. You could try changeing the definition of GetFriendByIndex on the D side to ulong GetFriendByIndex(...) and reinterpret the ulong on the D side. If that does not work however you are most likely out of luck because the way your c++ library returns a value type > 32-bit is not compatible with what dmd expects. Do you have debug symbols for the third party c++ library? Can you step into the virtual function call to actually see if it ends up in the correct function on the c++ side? Kind Regards Benjamin Thaut
Apr 29 2015
parent reply "extrawurst" <stephan extrawurst.org> writes:
On Wednesday, 29 April 2015 at 13:55:46 UTC, Benjamin Thaut wrote:
 On Monday, 27 April 2015 at 21:19:02 UTC, extrawurst wrote:
 here is the shortened version of the returned class CSteamID:
 https://gist.github.com/Extrawurst/936f56ceaa87cf287257

 this is the shortened interface (no destructors in the rest of 
 the code either):
 https://gist.github.com/Extrawurst/b20dc5ab84132ecab30d

 the method `GetFriendByIndex` is the one crashing on win32.
I assume that's because CSteamID is returned by value. Are you defining CSteamID in D as a struct? If not you have to because only structs can be returned by value. The next problem is that CSteamID is 64bits wide, this might be a problem as it can not be returned in a single register. You could try changeing the definition of GetFriendByIndex on the D side to ulong GetFriendByIndex(...) and reinterpret the ulong on the D side. If that does not work however you are most likely out of luck because the way your c++ library returns a value type > 32-bit is not compatible with what dmd expects. Do you have debug symbols for the third party c++ library? Can you step into the virtual function call to actually see if it ends up in the correct function on the c++ side? Kind Regards Benjamin Thaut
Seems i am out of luck. I tried all that. The Steamworks SDK is closed source without debugging symbols. so it wont work.. too bad, this library would have been a good example case of seamless c++-interfacing from D...
Apr 29 2015
parent reply "Benjamin Thaut" <code benjamin-thaut.de> writes:
On Wednesday, 29 April 2015 at 19:04:11 UTC, extrawurst wrote:
 On Wednesday, 29 April 2015 at 13:55:46 UTC, Benjamin Thaut 
 wrote:
 On Monday, 27 April 2015 at 21:19:02 UTC, extrawurst wrote:
 here is the shortened version of the returned class CSteamID:
 https://gist.github.com/Extrawurst/936f56ceaa87cf287257

 this is the shortened interface (no destructors in the rest 
 of the code either):
 https://gist.github.com/Extrawurst/b20dc5ab84132ecab30d

 the method `GetFriendByIndex` is the one crashing on win32.
I assume that's because CSteamID is returned by value. Are you defining CSteamID in D as a struct? If not you have to because only structs can be returned by value. The next problem is that CSteamID is 64bits wide, this might be a problem as it can not be returned in a single register. You could try changeing the definition of GetFriendByIndex on the D side to ulong GetFriendByIndex(...) and reinterpret the ulong on the D side. If that does not work however you are most likely out of luck because the way your c++ library returns a value type > 32-bit is not compatible with what dmd expects. Do you have debug symbols for the third party c++ library? Can you step into the virtual function call to actually see if it ends up in the correct function on the c++ side? Kind Regards Benjamin Thaut
Seems i am out of luck. I tried all that. The Steamworks SDK is closed source without debugging symbols. so it wont work.. too bad, this library would have been a good example case of seamless c++-interfacing from D...
Did you try windows 64-bit? Calling conventions on 64-bit windows are better standardized.
Apr 30 2015
parent "extrawurst" <stephan extrawurst.org> writes:
On Thursday, 30 April 2015 at 08:18:16 UTC, Benjamin Thaut wrote:
 On Wednesday, 29 April 2015 at 19:04:11 UTC, extrawurst wrote:
 On Wednesday, 29 April 2015 at 13:55:46 UTC, Benjamin Thaut 
 wrote:
 On Monday, 27 April 2015 at 21:19:02 UTC, extrawurst wrote:
 here is the shortened version of the returned class CSteamID:
 https://gist.github.com/Extrawurst/936f56ceaa87cf287257

 this is the shortened interface (no destructors in the rest 
 of the code either):
 https://gist.github.com/Extrawurst/b20dc5ab84132ecab30d

 the method `GetFriendByIndex` is the one crashing on win32.
I assume that's because CSteamID is returned by value. Are you defining CSteamID in D as a struct? If not you have to because only structs can be returned by value. The next problem is that CSteamID is 64bits wide, this might be a problem as it can not be returned in a single register. You could try changeing the definition of GetFriendByIndex on the D side to ulong GetFriendByIndex(...) and reinterpret the ulong on the D side. If that does not work however you are most likely out of luck because the way your c++ library returns a value type
 32-bit is not compatible with what dmd expects. Do you have
debug symbols for the third party c++ library? Can you step into the virtual function call to actually see if it ends up in the correct function on the c++ side? Kind Regards Benjamin Thaut
Seems i am out of luck. I tried all that. The Steamworks SDK is closed source without debugging symbols. so it wont work.. too bad, this library would have been a good example case of seamless c++-interfacing from D...
Did you try windows 64-bit? Calling conventions on 64-bit windows are better standardized.
no i did not, win64-only is a no-option unfortunately
Apr 30 2015