Interfacing with C++
Hi all I'm looking to try and write an interface to C++, but given I'm a casual dabbler in D, it's slightly beyond my current ability in terms of both C++ and D! As a leg up, how would one translate something like this from C++ to D? `typedef int (CV_CDECL* CvCmpFunc)(const void* a, const void* b, void* userdata );` From my basic understanding I assumed something like: `alias CvCmpFunc = Typedef!(int) ; ` but then I'm stuck as to where the rest of the parameters would get passed? Do I just declare it as a function instead? That wasn't my understanding of reading how typedefs worked, however so I'm a little confused. Any help would be appreciated. Regards
Interfacing with C++
Hello. I really really need to be able to interface well with a C++ library which contains lots of classes if I am going to further invest time into D. Now from the http://dlang.org/cpp_interface I find out the current status of built-in C++ interfacing support. I'm working on Linux so using the COM support is not an option for me (whatever COM may be!). A few queries: 1) How mature is the SWIG support for wrapping a library into D? Specifically does the above SWIG support take advantage of the built-in C++ support features like connecting directly to virtual functions? 2) Is there any further work underway to implement support for static and non-virtual class member functions? Or is this not at all possible? If so, why? 3) The page speaks about having to integrate an entire C++ compiler into the D compiler. Could the usage of libclang help here in having to avoid writing a new C++ compiler module or am I talking through my (non-existent) hat? -- Shriramana Sharma ஶ்ரீரமணஶர்மா श्रीरमणशर्मा
Re: Interfacing with C++
On 04/02/2018 7:54 AM, infinityplusb wrote: Hi all I'm looking to try and write an interface to C++, but given I'm a casual dabbler in D, it's slightly beyond my current ability in terms of both C++ and D! As a leg up, how would one translate something like this from C++ to D? `typedef int (CV_CDECL* CvCmpFunc)(const void* a, const void* b, void* userdata );` From my basic understanding I assumed something like: `alias CvCmpFunc = Typedef!(int) ; ` but then I'm stuck as to where the rest of the parameters would get passed? Do I just declare it as a function instead? That wasn't my understanding of reading how typedefs worked, however so I'm a little confused. Any help would be appreciated. Regards alias CvCmpFunc = extern(C /* I think */) int function(const void* a, const void* b, void* userdata);
Re: Interfacing with C++
On Sunday, 4 February 2018 at 07:54:12 UTC, infinityplusb wrote: Hi all I'm looking to try and write an interface to C++, but given I'm a casual dabbler in D, it's slightly beyond my current ability in terms of both C++ and D! As a leg up, how would one translate something like this from C++ to D? `typedef int (CV_CDECL* CvCmpFunc)(const void* a, const void* b, void* userdata );` From my basic understanding I assumed something like: `alias CvCmpFunc = Typedef!(int) ; ` but then I'm stuck as to where the rest of the parameters would get passed? Do I just declare it as a function instead? That wasn't my understanding of reading how typedefs worked, however so I'm a little confused. Any help would be appreciated. First, you have to understand how CV_CDECL is defined. This is going to determine the calling convention that functions pointed to by CvCmpFunc will have. Assuming it's defined to cdecl, the standard C calling convention (which I'm guess it is) then your D definition needs to be extern(C). If it's stdcall, then you need extern(Windows). If it's empty, then you need extern(C++). Second, because this is a function pointer you're declaring, you need to use D's function pointer declaration syntax. Third, we don't need to use the Typedef template for this. alias alone is fine. So assuming CV_CDECL is cdecl, this should do it: extern(C) alias CvCmpFunc = int function(const(void)*, const(void)*, void*);
Re: Interfacing with C++
On Sunday, 4 February 2018 at 08:17:31 UTC, Mike Parker wrote: So assuming CV_CDECL is cdecl, this should do it: extern(C) alias CvCmpFunc = int function(const(void)*, const(void)*, void*); Assuming this is OpenCV, Looking at [1], it's cdecl only on Windows. Empty everywhere else. So since OpenCV is a C++ library these days, I guess it needs to be declared like this: version(Windows) extern(C) alias CvCmpFunc = int function(const(void)*, const(void)*, void*); else extern(C++) alias CvCmpFunc = int function(const(void)*, const(void)*, void*); Though, I'm curious why anyone would want to declare a callback in a C++ program as cdecl only on Windows and use the default C++ convention everywhere else. I suggest you dig into it and make sure that's what's intended. And good luck binding to OpenCV! [1] https://github.com/opencv/opencv/blob/master/modules/core/include/opencv2/core/types_c.h#L68
Re: Interfacing with C++
On Sunday, 4 February 2018 at 08:33:20 UTC, Mike Parker wrote: On Sunday, 4 February 2018 at 08:17:31 UTC, Mike Parker wrote: Assuming this is OpenCV ... it is, everyone keeps saying writing bindings in D is super easy ... I feel this is a slight simplification. :( version(Windows) extern(C) alias CvCmpFunc = int function(const(void)*, const(void)*, void*); else extern(C++) alias CvCmpFunc = int function(const(void)*, const(void)*, void*); Sounds easy enough. Though, I'm curious why anyone would want to declare a callback in a C++ program as cdecl only on Windows and use the default C++ convention everywhere else. I suggest you dig into it and make sure that's what's intended. And good luck binding to OpenCV! Thanks, I feel I'm going to need it ...
Re: Interfacing with C++
On Sunday, 4 February 2018 at 10:42:22 UTC, infinityplusb wrote: On Sunday, 4 February 2018 at 08:33:20 UTC, Mike Parker wrote: [...] it is, everyone keeps saying writing bindings in D is super easy ... I feel this is a slight simplification. :( [...] Sounds easy enough. [...] [...] Thanks, I feel I'm going to need it ... For C headers, you can use dstep to automatically generate the respective D header file: https://github.com/jacob-carlborg/dstep
Re: Interfacing with C++
On Sun, 04 Feb 2018 08:33:20 +, Mike Parker wrote: > Though, I'm curious why anyone would want to declare a callback in a C++ > program as cdecl only on Windows and use the default C++ > convention everywhere else. I suggest you dig into it and make sure > that's what's intended. And good luck binding to OpenCV! My guess would be that it's to prevent name mangling of functions in a generated DLL and the need for a DEF file.
Re: Interfacing with C++
Calypso (https://github.com/Syniurge/Calypso/) is the most promising way to interface with C++, it requires 0 bindings and understands all of C++ (templates etc); there are some caveats/kinks that are being ironed out (and any help is welcome). On Sun, Feb 4, 2018 at 4:37 AM, rjframe via Digitalmars-d-learn wrote: > On Sun, 04 Feb 2018 08:33:20 +, Mike Parker wrote: > >> Though, I'm curious why anyone would want to declare a callback in a C++ >> program as cdecl only on Windows and use the default C++ >> convention everywhere else. I suggest you dig into it and make sure >> that's what's intended. And good luck binding to OpenCV! > > My guess would be that it's to prevent name mangling of functions in a > generated DLL and the need for a DEF file.
Re: Interfacing with C++
On Sunday, 4 February 2018 at 08:33:20 UTC, Mike Parker wrote: Though, I'm curious why anyone would want to declare a callback in a C++ program as cdecl only on Windows and use the default C++ convention everywhere else. I suggest you dig into it and make sure that's what's intended. And good luck binding to OpenCV! [1] https://github.com/opencv/opencv/blob/master/modules/core/include/opencv2/core/types_c.h#L68 No, it's C everywhere, see https://github.com/opencv/opencv/blob/master/modules/core/include/opencv2/core/types_c.h#L1774
Re: Interfacing with C++
https://github.com/opencv/opencv/issues/6585#issuecomment-221842441 snip: > "C-API" is not supported and should be removed totally (but we have a lack of > resources to port this legacy C code to C++, so some of this code still > exists right now). Also huge part of fresh OpenCV functionality is missing in > "C-API". There is no plan to fix this in OpenCV directly. http://answers.opencv.org/question/17546/opencv-will-drop-c-api-support-soon/ snip: > Shervin is right, the C API is not developed for a long time. All the new > stuff has the C++ API, and it is not backported to the C. So, C API becomes > obsolete and causes pain in the neck, since it should be maintained I recommend trying out Calypso and helping ironing out any bugs you may find. On Mon, Feb 5, 2018 at 3:15 AM, Kagamin via Digitalmars-d-learn wrote: > On Sunday, 4 February 2018 at 08:33:20 UTC, Mike Parker wrote: >> >> Though, I'm curious why anyone would want to declare a callback in a C++ >> program as cdecl only on Windows and use the default C++ convention >> everywhere else. I suggest you dig into it and make sure that's what's >> intended. And good luck binding to OpenCV! >> >> >> [1] >> https://github.com/opencv/opencv/blob/master/modules/core/include/opencv2/core/types_c.h#L68 > > > No, it's C everywhere, see > https://github.com/opencv/opencv/blob/master/modules/core/include/opencv2/core/types_c.h#L1774
Re: Interfacing with C++
You can see http://wiki.dlang.org/DIP61 and linked discussions. Static and virtual functions probably work. Constructors and destructors probably don't. What's difficult is multiple inheritance. The information on C++ support is largely considered private to the compiler team.
Re: Interfacing with C++
D.learn is about basics of D. Interfacing with C++ is an advanced topic, with feature set in flux, so I'd suggest to ask about it in http://forum.dlang.org/group/digitalmars.D group.
Callbacks and interfacing with C
Ok, a C function pointer like this: struct MyStruct{ int (*foo)(int); }; Translates to D as this: struct MyStruct{ int function(int) foo; } But what about calling conventions? There isn't any "int extern(C) function(int)" is there? Not sure if that would even make sense. So do you just make sure that whatever func you assign to it is an extern(C)? Or something else?
Interfacing with C++ Class named Object
Hi, I'm mostly doing simple C-API wrappers around C++ code to access thigns from D. However, I wanted to try how far I can come using C++ directly. I have the following C++ code in namespace N: class Image : public Object { Error create(int w, int h, uint32_t p) noexcept; } And I have the following D code: extern (C++, N) { class Object { } class Image : public Object { uint create(int w, int h, uint pixelFormat); } } So frist problem I see is, that a C++ class names Object is pretty unfortunate as this is a reserved class name in D. And DMD doesn't seem to allow using Object inside a C++ scope (which IMO should be possible). Am I right, that there is no chance to handle this case other than ranming the C++ base class? -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Re: Callbacks and interfacing with C
On 30-10-2012 11:13, Nick Sabalausky wrote: Ok, a C function pointer like this: struct MyStruct{ int (*foo)(int); }; Translates to D as this: struct MyStruct{ int function(int) foo; } But what about calling conventions? There isn't any "int extern(C) function(int)" is there? Not sure if that would even make sense. So do you just make sure that whatever func you assign to it is an extern(C)? Or something else? You generally do it this way: alias extern (C) int function(int) MyFn; struct MyStruct { MyFn foo; } This makes sure the calling convention is correct. In general, calling convention is part of both the function signature and function pointer type - function pointers just default to extern (D). -- Alex Rønne Petersen a...@lycus.org http://lycus.org
Re: Callbacks and interfacing with C
On Tue, 30 Oct 2012 11:15:55 +0100 Alex Rønne Petersen wrote: > On 30-10-2012 11:13, Nick Sabalausky wrote: > > Ok, a C function pointer like this: > > > > struct MyStruct{ > > int (*foo)(int); > > }; > > > > Translates to D as this: > > > > struct MyStruct{ > > int function(int) foo; > > } > > > > But what about calling conventions? There isn't any "int extern(C) > > function(int)" is there? Not sure if that would even make sense. > > > > So do you just make sure that whatever func you assign to it is an > > extern(C)? Or something else? > > > > You generally do it this way: > > alias extern (C) int function(int) MyFn; > > struct MyStruct { > MyFn foo; > } > > This makes sure the calling convention is correct. In general, > calling convention is part of both the function signature and > function pointer type - function pointers just default to extern (D). > Hmm, that leads me to another Q: extern(C): // <-- Note this alias int function(int) MyFn; struct MyStruct { MyFn foo1; int function(int) foo2; } void bar(int function(int) foo3) {...} Which, if any, of foo1/foo2/foo3 are extern(C)? (I know bar definitely is.)
Re: Callbacks and interfacing with C
Nick Sabalausky: Which, if any, of foo1/foo2/foo3 are extern(C)? (I know bar definitely is.) A general comment: if you are not sure of the answer, then the programmer that will read your code will probably have similar problems. So in such cases it's better to try to not write that code. Bye, bearophile
Re: Callbacks and interfacing with C
On 10/30/12, Nick Sabalausky wrote: > Which, if any, of foo1/foo2/foo3 are extern(C)? (I know bar definitely > is.) All of them. void main() { pragma(msg, MyFn); pragma(msg, typeof(MyStruct.foo2)); pragma(msg, typeof(bar)); } extern (C) int function(int) extern (C) int function(int) extern (C) void(extern (C) int function(int) foo3) extern (C) int function(int) extern (C) int function(int) extern (C) void(extern (C) int function(int) foo3) It's because extern(C): leaks everywhere, whether on purpose or not. It can be a benefit for writing shorter code, but when reading such code it's easy to forget to check for an extern(C): declaration at the top and just wrongly assume that it's all extern(D).
Re: Callbacks and interfacing with C
On 2012-10-30 18:44, Andrej Mitrovic wrote: All of them. void main() { pragma(msg, MyFn); pragma(msg, typeof(MyStruct.foo2)); pragma(msg, typeof(bar)); } extern (C) int function(int) extern (C) int function(int) extern (C) void(extern (C) int function(int) foo3) extern (C) int function(int) extern (C) int function(int) extern (C) void(extern (C) int function(int) foo3) It's because extern(C): leaks everywhere, whether on purpose or not. It can be a benefit for writing shorter code, but when reading such code it's easy to forget to check for an extern(C): declaration at the top and just wrongly assume that it's all extern(D). It doesn't leak into local declarations in a function: extern (C): void foo () { alias void function () Foo; void function (int) a; auto b = cast(void function ()) a; pragma(msg, Foo); pragma(msg, typeof(a)); pragma(msg, typeof(b)); } void function() void function(int) void function() -- /Jacob Carlborg
Re: Interfacing with C++ Class named Object
On Tuesday, 1 May 2018 at 15:24:09 UTC, Robert M. Münch wrote: Hi, I'm mostly doing simple C-API wrappers around C++ code to access thigns from D. However, I wanted to try how far I can come using C++ directly. I have the following C++ code in namespace N: class Image : public Object { Error create(int w, int h, uint32_t p) noexcept; } And I have the following D code: extern (C++, N) { class Object { } class Image : public Object { uint create(int w, int h, uint pixelFormat); } } So frist problem I see is, that a C++ class names Object is pretty unfortunate as this is a reserved class name in D. And DMD doesn't seem to allow using Object inside a C++ scope (which IMO should be possible). Am I right, that there is no chance to handle this case other than ranming the C++ base class? Would `pragma(mangle, ...)` work here? https://dlang.org/spec/pragma.html#mangle
Re: Interfacing with C++ Class named Object
On 2018-05-01 16:07:30 +, Timoses said: On Tuesday, 1 May 2018 at 15:24:09 UTC, Robert M. Münch wrote: Hi, I'm mostly doing simple C-API wrappers around C++ code to access thigns from D. However, I wanted to try how far I can come using C++ directly. I have the following C++ code in namespace N: class Image : public Object { Error create(int w, int h, uint32_t p) noexcept; } And I have the following D code: extern (C++, N) { class Object { } class Image : public Object { uint create(int w, int h, uint pixelFormat); } } So frist problem I see is, that a C++ class names Object is pretty unfortunate as this is a reserved class name in D. And DMD doesn't seem to allow using Object inside a C++ scope (which IMO should be possible). Am I right, that there is no chance to handle this case other than ranming the C++ base class? Would `pragma(mangle, ...)` work here? https://dlang.org/spec/pragma.html#mangle Yes, great! Thanks. I could extend the code now. But I get a next problem: extern (C++, b2d) { class AnyBase { bool isShared(); } pragma(mangle, "Object"); class b2dObject : AnyBase { } class Image : b2dObject { // class Image { uint create(int w, int h, uint pixelFormat); } } The linke complains about missing symbols: error LNK2001: "public: virtual bool __cdecl b2d::AnyBase::isShared(void)" (?isShared@AnyBase@b2d@@UEBA_NXZ) error LNK2001: "public: virtual unsigned int __cdecl b2d::Image::create(int,int,unsigned int)" (?create@Image@b2d@@UEAAIHHI@Z) I have in my C++ link lib: ?isShared@AnyBase@b2d@@QEBA_NXZ which demangles to => public: BOOL __cdecl b2d::AnyBase::isShared(void)const __ptr64 So, the difference is the "virtual" specifier on the D side, while the C++ mangeling is missing this. I have this for many functions. Any idea how to handle this? -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Re: Interfacing with C++ Class named Object
On 2018-05-01 17:14:53 +, Robert M. Münch said: Yes, great! Thanks. I could extend the code now. But I get a next problem: extern (C++, b2d) { class AnyBase { bool isShared(); } pragma(mangle, "Object"); class b2dObject : AnyBase { } class Image : b2dObject { // class Image { uint create(int w, int h, uint pixelFormat); } } The linke complains about missing symbols: error LNK2001: "public: virtual bool __cdecl b2d::AnyBase::isShared(void)" (?isShared@AnyBase@b2d@@UEBA_NXZ) error LNK2001: "public: virtual unsigned int __cdecl b2d::Image::create(int,int,unsigned int)" (?create@Image@b2d@@UEAAIHHI@Z) I have in my C++ link lib: ?isShared@AnyBase@b2d@@QEBA_NXZ which demangles to => public: BOOL __cdecl b2d::AnyBase::isShared(void)const __ptr64 So, the difference is the "virtual" specifier on the D side, while the C++ mangeling is missing this. I have this for many functions. Any idea how to handle this? Answering myself. There is a final keyword missing: class Image : b2dObject { // class Image { final uint create(int w, int h, uint pixelFormat); } With this it's working. -- Robert M. Münch http://www.saphirion.com smarter | better | faster
interfacing with C: strings and byte vectors
my C library works a lot with strings defined in C as: struct vec_t { char *base; size_t len; } is there a easy way to feed regular D strings to functions that accept vec_t* without creating a vec_t every time or do i write wrappers for these functions and if so, what is the most elegant way to build them? so far i defined vec_t as: struct vec_t { char *base; size_t len; this(string s) { base = s.ptr; len = s.lenght; } nothrow @nogc inout(char)[] toString() inout @property { return base[0 .. len]; } nothrow @nogc @property const(char)[] toSlice() { return cast(string) base[0..len]; } alias toString this; } but i guess there is a more elegant way?!
Small structs: interfacing with C++ potentially broken
I have a small struct that I'm trying to interface to. C++ ```cpp struct __declspec(dllexport) SmallStruct { float value = 0; //float value2 = 0; //float value3 = 0; SmallStruct(float val) : value(val) { } static SmallStruct GetValue(float input) { return SmallStruct(input * 3.141f); } }; ``` And on the D side: ```cpp extern(C++) struct SmallStruct { float value = 0; // float value2 = 0; // float value3 = 0; static SmallStruct GetValue(float input); }; ``` Then I use it like this: ```cpp SmallStruct s = SmallStruct.GetValue(3); ``` Running this crashes on the C++ side, with an access violation writing data. Looking at the disassembly, it seems that C++ expects the Smallstruct return object to be passed in, whereas D assumes that the SmallStruct is passed through registers. This is with MVSC 2019 compiled for x64 and DMD v2.098.0. If I enable 'value2' and 'value3', it seems that both compilers start to agree on the calling convention. Is this a known issue, or is there a way to instruct DMD to use a specific calling convention for a given type?
Interfacing with c and platform dependent sizes
C is not my strong side, so I'm having some problems wrapping some code. I found a couple of sources on this: 1) http://www.digitalmars.com/d/2.0/htomodule.html 2) http://www.digitalmars.com/d/2.0/interfaceToC.html 1) C's long is the same as D's int. long long is long 2) C 32bit's long long is D's long, C 64 bits long is D's long. So.. A long in C is the same as the platform size? And long long doesn't exist in 64 bit?
Using a delegate when interfacing with C
Hi, I'm quite new to D and I'm not able to find out what I'm doing wrong. Consider the following code: class ClientImplementation { private ProcessDelegate processDelegate; void setProcessDelegate(ProcessDelegate deleg) { this.processDelegate = deleg; extern(C) ProcessCallback callback = function int(NFrames nframes, void* data) { auto client = *(cast(ClientImplementation*) data); return client.processDelegate(nframes); }; this.setProcessCallback(callback, cast(void *) &this); } In my D wrapper for a C API I want to use delegates. The C API accepts a callback which has a generic void* parameter which can be specified when setting the callback (it will be stored and passed in the callback when it gets called... a common pattern in C APIs). So I want to use it to make delegates possible. The problem with this approach is that I get a segmentation fault on the line: auto client = *(cast(ClientImplementation*) data); as soon as the callback is called the first time. The callback is called in another thread (but this shouldn't be a problem since ClientImplementation is a class and therefore instances are created in the heap). Can somebody help me in figuring out why this happens? I also tried unsuccesfully auto client = cast(ClientImplementation*) data;
Re: interfacing with C: strings and byte vectors
On Saturday, 11 June 2016 at 09:32:54 UTC, yawniek wrote: so far i defined vec_t as: struct vec_t { char *base; size_t len; this(string s) { base = s.ptr; len = s.lenght; } nothrow @nogc inout(char)[] toString() inout @property { return base[0 .. len]; } nothrow @nogc @property const(char)[] toSlice() { return cast(string) base[0..len]; } alias toString this; } but i guess there is a more elegant way?! No, you've got the right idea with the constructor. You just need to change your implementation. You have two big problems with your current constructor. First, only string literals in D (e.g. "foo") are guaranteed to be null terminated. If you construct a vec_t with a string that is not a literal, then you can have a problem on the C side where it is expected to be null terminated. Second, if the string you pass to the constructor was allocated on the GC heap and at some point is collected, then base member of the vec_t will point to an invalid memory location. A simple approach would be: this(string s) { import std.string : toStringz; base = s.toStringz(); len = s.length; } Second, your toString and toSlice implementations are potentially problematic. Aside from the fact that toString is returning a slice and toSlice is returning a string, the slice you create there will always point to the same location as base. If base becomes invalid, then so will the slice. For the toString impelementation, you really should be doing something like this: string toString() nothrow inout { import std.conv.to; return to!string(base); } I don't know what benefit you are expecting from the toSlice method. If you absolutely need it, you should return implement it like so: char[] toSlice() nothrow inout { return base[0 .. len].dup; } This will give you a character array that is modifiable without worrying about the what happens to base. If you really want, you can declare the return as const(char)[]. Rather than toSlice, which isn't something the compiler is aware of, it would be much more appropriate to implement opSlice along with opDollar. Then it's possible to do this: auto slice = myVec[0 .. $]. Of course, if you don't want to allow aribrary slices, then perhaps toSlice is better.
Re: interfacing with C: strings and byte vectors
On Saturday, 11 June 2016 at 10:26:17 UTC, Mike Parker wrote: On Saturday, 11 June 2016 at 09:32:54 UTC, yawniek wrote: thanks mike for the in depth answer. i forgot to add a few important points: - the strings in vec_t are not c strings - vec_t might contain other data than strings the original ctor i pasted actually doesn't even work, temporarly i solved it like this(string s) { char[] si = cast(char[]) s; //i'm scared base = si.ptr; len = si.length; } is there a better solution than to fearlessly cast away immutability? i guess i could just make a second vec_t that has immutable base and length that can be used in D to stay clean, would that be worth anything? now what i still don't have a proper idea for is how can i create wrappers for the methods accepting vec_t in a clean way. for the vec_t that are allocated in D-land we can state that the C libs will not modify the data. there is a lot of functions that accept vec_t. is there no way to have strings auto cast to vec_t ? another way i see is a UDA that generates the wrapper function(s). other ideas?
Re: interfacing with C: strings and byte vectors
On 06/11/2016 01:59 PM, yawniek wrote: i forgot to add a few important points: - the strings in vec_t are not c strings - vec_t might contain other data than strings the original ctor i pasted actually doesn't even work, temporarly i solved it like this(string s) { char[] si = cast(char[]) s; //i'm scared Rightfully so. Casting away immutable shouldn't be done lightly. base = si.ptr; len = si.length; } is there a better solution than to fearlessly cast away immutability? i guess i could just make a second vec_t that has immutable base and length that can be used in D to stay clean, would that be worth anything? Sure. You wouldn't have to do the risky cast then. now what i still don't have a proper idea for is how can i create wrappers for the methods accepting vec_t in a clean way. for the vec_t that are allocated in D-land we can state that the C libs will not modify the data. there is a lot of functions that accept vec_t. is there no way to have strings auto cast to vec_t ? I don't think so, no. You can make a new type and use alias this to have it convert implicitly to vec_t, but you can't enable that for string. There is no feature to implicitly convert *from* another type, only *to* another type. another way i see is a UDA that generates the wrapper function(s). other ideas? Generating the wrappers seems ok to me. Regarding a UDA: I haven't really used them, but you'd still have to iterate over all functions that have the attribute, right? At that point, the UDA might be pointless. Can also iterate over everything and check if there's a vec_t parameter.
Re: Small structs: interfacing with C++ potentially broken
On Monday, 20 December 2021 at 10:24:00 UTC, Jan wrote: Is this a known issue, or is there a way to instruct DMD to use a specific calling convention for a given type? This looks like a bug. It seems to work without constructor in C++, but still crashes with a constructor in D. It also seems to work if a trivial destructor is added in D: ~this(){} This could be related to POD types in C++. Structs with constructor or destructor are probably passed differently, but dmd only looks at the destructor.
Re: Small structs: interfacing with C++ potentially broken
On Monday, 20 December 2021 at 11:58:03 UTC, Tim wrote: On Monday, 20 December 2021 at 10:24:00 UTC, Jan wrote: Is this a known issue, or is there a way to instruct DMD to use a specific calling convention for a given type? This looks like a bug. It seems to work without constructor in C++, but still crashes with a constructor in D. It also seems to work if a trivial destructor is added in D: ~this(){} This could be related to POD types in C++. Structs with constructor or destructor are probably passed differently, but dmd only looks at the destructor. I think it's got something to do with [this](https://forum.dlang.org/post/capevemlbdanirtcj...@forum.dlang.org)
Re: Small structs: interfacing with C++ potentially broken
On Monday, 20 December 2021 at 11:58:03 UTC, Tim wrote: On Monday, 20 December 2021 at 10:24:00 UTC, Jan wrote: Is this a known issue, or is there a way to instruct DMD to use a specific calling convention for a given type? This looks like a bug. It seems to work without constructor in C++, but still crashes with a constructor in D. It also seems to work if a trivial destructor is added in D: ~this(){} This could be related to POD types in C++. Structs with constructor or destructor are probably passed differently, but dmd only looks at the destructor. Well, that at least gives me a way to work around this issue.
Interfacing with C++ std::shared_ptr and std::unique_ptr
Hi, I would like to interface with the library https://github.com/NTNU-IHB/FMI4cpp and have following class definitions in the header file: ``` c++ namespace fmi4cpp { template class fmu_base { public: const std::string guid() const { return get_model_description()->guid; } const std::string model_name() const { return get_model_description()->model_name; } virtual std::shared_ptr get_model_description() const = 0; }; template class fmu_provider : public virtual fmu_base { public: virtual bool supports_cs() const = 0; virtual bool supports_me() const = 0; virtual std::unique_ptr as_cs_fmu() const = 0; virtual std::unique_ptr as_me_fmu() const = 0; }; ``` While unique_ptr is already available in drunime library core.stdcpp.memory, shared_ptr is missing. Does someone already have translated shared_ptr? Also, the C++ classes make use of templates. Is it still possible to call these classes from D? Kind regards Andre
Re: Interfacing with c and platform dependent sizes
simendsjo: > So.. A long in C is the same as the platform size? And long long doesn't > exist in 64 bit? In D the size of int/uint is 32 bits and long/ulong is 64 bits. In C the size of int, unsigned int, long, long long int, unsigned long long int, etc are not fixed, the change according to the CPU. sizeof(int) <= sizeof(long) <= sizeof(long long). A help: http://www.digitalmars.com/d/2.0/phobos/std_stdint.html Bye, bearophile
Re: Interfacing with c and platform dependent sizes
On 26.02.2011 02:06, bearophile wrote: simendsjo: So.. A long in C is the same as the platform size? And long long doesn't exist in 64 bit? In D the size of int/uint is 32 bits and long/ulong is 64 bits. In C the size of int, unsigned int, long, long long int, unsigned long long int, etc are not fixed, the change according to the CPU. sizeof(int)<= sizeof(long)<= sizeof(long long). A help: http://www.digitalmars.com/d/2.0/phobos/std_stdint.html Bye, bearophile Ouch.. Any tips on porting C code that would work nicely with a transition to 64 bit? Should I change all long and int to int_atleast_32_t and long long to 64?
Re: Interfacing with c and platform dependent sizes
On Friday, February 25, 2011 17:16:31 simendsjo wrote: > On 26.02.2011 02:06, bearophile wrote: > > simendsjo: > >> So.. A long in C is the same as the platform size? And long long doesn't > >> exist in 64 bit? > > > > In D the size of int/uint is 32 bits and long/ulong is 64 bits. > > > > In C the size of int, unsigned int, long, long long int, unsigned long > > long int, etc are not fixed, the change according to the CPU. > > sizeof(int)<= sizeof(long)<= sizeof(long long). > > > > A help: > > http://www.digitalmars.com/d/2.0/phobos/std_stdint.html > > > > Bye, > > bearophile > > Ouch.. Any tips on porting C code that would work nicely with a > transition to 64 bit? > Should I change all long and int to int_atleast_32_t and long long to 64? It depends entirely on what the code is doing. It could be completely safe to convert all ints, longs, and long longs to long to long. Or you may have to choose int or long depending on what system the code is supposed to be for. In many cases, using a larger type wouldn't matter, since it can hold more than the smaller type, so whether the type in C/C++ was 32 bits or 64 bits is irrelevant. In other cases, the type needs to be an exact size, because the code is doing bit shifts or whatnot (in which case they _should_ have been using int32_t and int64_t on Linux and whatever the equivalent is on Windows, but unfortunately, many programmers don't). And if you're dealing with a struct, it's possible that that struct has to be an exact size (e.g. for some binary format), and using the wrong type in converting could make it the wrong size. If you want to know what the appropriate D type is for the C/C++ code, you _need_ to know what it does. Now, IIRC, int is almost guaranteed to be 32 bits at this point, and long long is essentially guaranteed to be 64 bits, but long varies from system to system - both in terms of OS and architecture. IIRC, long is 32 bits on Solaris and Windows - both on x86 and x86_64 - but it's 32 bits in x86 Linux and 64 bits in x86_64 Linux. So, if all the code uses is int and long long, then it's probably reasonably safe to use int for int and long for long long, but it's ultimately system dependent. Personally, I would argue that C/C++ code should use int when you don't care about the size of an integral type and use the intX_t types (where X is 8, 16, 32, or 64) when you _do_ care about the size, but there's no guarantee that programmers are going to be that disciplined about it. In any case, if you really don't know the code and don't want to take the time to understand it, I'd use int for int, long for long long, and then if they have long, I'd do the research to figure out which OS and architecture the code is supposed to be for and use int if long long is 32 bits and long if it's 64 bits. If you don't know what system it was built for, then I'd probably just use long and hoped that they weren't doing anything that made using an integral type which was too large a problem. - Jonathan M Davis
Re: Interfacing with c and platform dependent sizes
On Fri, 25 Feb 2011 20:06:04 -0500, bearophile wrote: simendsjo: So.. A long in C is the same as the platform size? And long long doesn't exist in 64 bit? In D the size of int/uint is 32 bits and long/ulong is 64 bits. In C the size of int, unsigned int, long, long long int, unsigned long long int, etc are not fixed, the change according to the CPU. sizeof(int) <= sizeof(long) <= sizeof(long long). It's *recommended* that ints be the size of a standard register. So, those sizes do not have to follow the CPU architecture, and compilers could potentially use different sizes even on the same platform. D (and most languages that came after C) did a much better job on this. BTW, I think long long is a gnu extension, it's not standard C (I don't think long long exists in Visual C for instance). -Steve
Re: Interfacing with c and platform dependent sizes
On Friday, February 25, 2011 17:35:02 Jonathan M Davis wrote: > On Friday, February 25, 2011 17:16:31 simendsjo wrote: > > On 26.02.2011 02:06, bearophile wrote: > > > simendsjo: > > >> So.. A long in C is the same as the platform size? And long long > > >> doesn't exist in 64 bit? > > > > > > In D the size of int/uint is 32 bits and long/ulong is 64 bits. > > > > > > In C the size of int, unsigned int, long, long long int, unsigned long > > > long int, etc are not fixed, the change according to the CPU. > > > sizeof(int)<= sizeof(long)<= sizeof(long long). > > > > > > A help: > > > http://www.digitalmars.com/d/2.0/phobos/std_stdint.html > > > > > > Bye, > > > bearophile > > > > Ouch.. Any tips on porting C code that would work nicely with a > > transition to 64 bit? > > Should I change all long and int to int_atleast_32_t and long long to 64? > > It depends entirely on what the code is doing. It could be completely safe > to convert all ints, longs, and long longs to long to long. Or you may > have to choose int or long depending on what system the code is supposed > to be for. > > In many cases, using a larger type wouldn't matter, since it can hold more > than the smaller type, so whether the type in C/C++ was 32 bits or 64 bits > is irrelevant. In other cases, the type needs to be an exact size, because > the code is doing bit shifts or whatnot (in which case they _should_ have > been using int32_t and int64_t on Linux and whatever the equivalent is on > Windows, but unfortunately, many programmers don't). And if you're dealing > with a struct, it's possible that that struct has to be an exact size > (e.g. for some binary format), and using the wrong type in converting > could make it the wrong size. > > If you want to know what the appropriate D type is for the C/C++ code, you > _need_ to know what it does. Now, IIRC, int is almost guaranteed to be 32 > bits at this point, and long long is essentially guaranteed to be 64 bits, > but long varies from system to system - both in terms of OS and > architecture. IIRC, long is 32 bits on Solaris and Windows - both on x86 > and x86_64 - but it's 32 bits in x86 Linux and 64 bits in x86_64 Linux. > So, if all the code uses is int and long long, then it's probably > reasonably safe to use int for int and long for long long, but it's > ultimately system dependent. Personally, I would argue that C/C++ code > should use int when you don't care about the size of an integral type and > use the intX_t types (where X is 8, 16, 32, or 64) when you _do_ care > about the size, but there's no guarantee that programmers are going to be > that disciplined about it. > > In any case, if you really don't know the code and don't want to take the > time to understand it, I'd use int for int, long for long long, and then > if they have long, I'd do the research to figure out which OS and > architecture the code is supposed to be for and use int if long long is 32 > bits and long if it's 64 bits. If you don't know what system it was built > for, then I'd probably just use long and hoped that they weren't doing > anything that made using an integral type which was too large a problem. Actually, I just realized that I was thinking in terms of porting C++ code to D. You're going to have to be more strict if you're just converting header files. However, what you can do is just compile something like this in C/C++ on your system: printf("int -> %d bytes", sizeof(int)); printf("long -> %d bytes", sizeof(long)); printf("long long -> %d bytes", sizeof(long long)); Then you'll know what they are on your system, and you can convert them over just fine. You just have to remember to do the same on any other system that you compile your code on. Bleh. At least D went the route of standarizing the size of its primitive types. - Jonathan M Davis
Re: Interfacing with c and platform dependent sizes
On 2011-02-26 01:28, simendsjo wrote: C is not my strong side, so I'm having some problems wrapping some code. I found a couple of sources on this: 1) http://www.digitalmars.com/d/2.0/htomodule.html 2) http://www.digitalmars.com/d/2.0/interfaceToC.html 1) C's long is the same as D's int. long long is long 2) C 32bit's long long is D's long, C 64 bits long is D's long. So.. A long in C is the same as the platform size? And long long doesn't exist in 64 bit? In general you can follow the table at http://www.digitalmars.com/d/2.0/htomodule.html But when it comes to "long" in C you have to be careful. On 32bit platforms a C "long" will be 32bit long. But on 64bit platforms it depends of what data model is used. To simplify things: * On Windows 64bit a C "long" will be 32bit long * On Posix 64bit a C "long" will be 64bit long. What you can do is to create an alias called "c_long" and "c_ulong", something like this: version (D_LP64) { version (Windows) { alias int c_long; alias uint c_ulong; } else { alias long c_long; alias ulong c_ulong; } } else { alias int c_long; alias uint c_ulong; } To read more about data models: http://en.wikipedia.org/wiki/64-bit#Specific_C-language_data_models -- /Jacob Carlborg
Re: Interfacing with c and platform dependent sizes
On 2011-02-26 02:35, Jonathan M Davis wrote: On Friday, February 25, 2011 17:16:31 simendsjo wrote: On 26.02.2011 02:06, bearophile wrote: simendsjo: So.. A long in C is the same as the platform size? And long long doesn't exist in 64 bit? In D the size of int/uint is 32 bits and long/ulong is 64 bits. In C the size of int, unsigned int, long, long long int, unsigned long long int, etc are not fixed, the change according to the CPU. sizeof(int)<= sizeof(long)<= sizeof(long long). A help: http://www.digitalmars.com/d/2.0/phobos/std_stdint.html Bye, bearophile Ouch.. Any tips on porting C code that would work nicely with a transition to 64 bit? Should I change all long and int to int_atleast_32_t and long long to 64? It depends entirely on what the code is doing. It could be completely safe to convert all ints, longs, and long longs to long to long. Or you may have to choose int or long depending on what system the code is supposed to be for. In many cases, using a larger type wouldn't matter, since it can hold more than the smaller type, so whether the type in C/C++ was 32 bits or 64 bits is irrelevant. In other cases, the type needs to be an exact size, because the code is doing bit shifts or whatnot (in which case they _should_ have been using int32_t and int64_t on Linux and whatever the equivalent is on Windows, but unfortunately, many programmers don't). And if you're dealing with a struct, it's possible that that struct has to be an exact size (e.g. for some binary format), and using the wrong type in converting could make it the wrong size. If you want to know what the appropriate D type is for the C/C++ code, you _need_ to know what it does. Now, IIRC, int is almost guaranteed to be 32 bits at this point, and long long is essentially guaranteed to be 64 bits, but long varies from system to system - both in terms of OS and architecture. IIRC, long is 32 bits on Solaris and Windows - both on x86 and x86_64 - but it's 32 bits in x86 Linux and 64 bits in x86_64 Linux. So, if all the code uses is int and long long, then it's probably reasonably safe to use int for int and long for long long, but it's ultimately system dependent. Personally, I would argue that C/C++ code should use int when you don't care about the size of an integral type and use the intX_t types (where X is 8, 16, 32, or 64) when you _do_ care about the size, but there's no guarantee that programmers are going to be that disciplined about it. A C "long" is 64bit long on Solaris 64bit according to this: http://en.wikipedia.org/wiki/64-bit#Specific_C-language_data_models In any case, if you really don't know the code and don't want to take the time to understand it, I'd use int for int, long for long long, and then if they have long, I'd do the research to figure out which OS and architecture the code is supposed to be for and use int if long long is 32 bits and long if it's 64 bits. If you don't know what system it was built for, then I'd probably just use long and hoped that they weren't doing anything that made using an integral type which was too large a problem. - Jonathan M Davis -- /Jacob Carlborg
Re: Interfacing with c and platform dependent sizes
On Saturday 26 February 2011 02:51:08 Jacob Carlborg wrote: > On 2011-02-26 02:35, Jonathan M Davis wrote: > > On Friday, February 25, 2011 17:16:31 simendsjo wrote: > >> On 26.02.2011 02:06, bearophile wrote: > >>> simendsjo: > So.. A long in C is the same as the platform size? And long long > doesn't exist in 64 bit? > >>> > >>> In D the size of int/uint is 32 bits and long/ulong is 64 bits. > >>> > >>> In C the size of int, unsigned int, long, long long int, unsigned long > >>> long int, etc are not fixed, the change according to the CPU. > >>> sizeof(int)<= sizeof(long)<= sizeof(long long). > >>> > >>> A help: > >>> http://www.digitalmars.com/d/2.0/phobos/std_stdint.html > >>> > >>> Bye, > >>> bearophile > >> > >> Ouch.. Any tips on porting C code that would work nicely with a > >> transition to 64 bit? > >> Should I change all long and int to int_atleast_32_t and long long to > >> 64? > > > > It depends entirely on what the code is doing. It could be completely > > safe to convert all ints, longs, and long longs to long to long. Or you > > may have to choose int or long depending on what system the code is > > supposed to be for. > > > > In many cases, using a larger type wouldn't matter, since it can hold > > more than the smaller type, so whether the type in C/C++ was 32 bits or > > 64 bits is irrelevant. In other cases, the type needs to be an exact > > size, because the code is doing bit shifts or whatnot (in which case > > they _should_ have been using int32_t and int64_t on Linux and whatever > > the equivalent is on Windows, but unfortunately, many programmers > > don't). And if you're dealing with a struct, it's possible that that > > struct has to be an exact size (e.g. for some binary format), and using > > the wrong type in converting could make it the wrong size. > > > > If you want to know what the appropriate D type is for the C/C++ code, > > you _need_ to know what it does. Now, IIRC, int is almost guaranteed to > > be 32 bits at this point, and long long is essentially guaranteed to be > > 64 bits, but long varies from system to system - both in terms of OS and > > architecture. IIRC, long is 32 bits on Solaris and Windows - both on x86 > > and x86_64 - but it's 32 bits in x86 Linux and 64 bits in x86_64 Linux. > > So, if all the code uses is int and long long, then it's probably > > reasonably safe to use int for int and long for long long, but it's > > ultimately system dependent. Personally, I would argue that C/C++ code > > should use int when you don't care about the size of an integral type > > and use the intX_t types (where X is 8, 16, 32, or 64) when you _do_ > > care about the size, but there's no guarantee that programmers are going > > to be that disciplined about it. > > A C "long" is 64bit long on Solaris 64bit according to this: > http://en.wikipedia.org/wiki/64-bit#Specific_C-language_data_models Well, I've run into problems before due the size of long differing on Linux and Solaris and I thought that it was 64-bit Linux and 64-bit Solaris, but maybe it was actually 32-bit Solaris (I _know_ that it was 64-bit Linux though). Regardless, it just goes to show how careful you have to be when dealing with long in C and C++. - Jonathan M Davis
Re: Interfacing with c and platform dependent sizes
On 02/26/2011 11:49 AM, Jacob Carlborg wrote: On 2011-02-26 01:28, simendsjo wrote: C is not my strong side, so I'm having some problems wrapping some code. I found a couple of sources on this: 1) http://www.digitalmars.com/d/2.0/htomodule.html 2) http://www.digitalmars.com/d/2.0/interfaceToC.html 1) C's long is the same as D's int. long long is long 2) C 32bit's long long is D's long, C 64 bits long is D's long. So.. A long in C is the same as the platform size? And long long doesn't exist in 64 bit? In general you can follow the table at http://www.digitalmars.com/d/2.0/htomodule.html But when it comes to "long" in C you have to be careful. On 32bit platforms a C "long" will be 32bit long. But on 64bit platforms it depends of what data model is used. To simplify things: * On Windows 64bit a C "long" will be 32bit long * On Posix 64bit a C "long" will be 64bit long. What you can do is to create an alias called "c_long" and "c_ulong", something like this: version (D_LP64) { version (Windows) { alias int c_long; alias uint c_ulong; } else { alias long c_long; alias ulong c_ulong; } } else { alias int c_long; alias uint c_ulong; } To read more about data models: http://en.wikipedia.org/wiki/64-bit#Specific_C-language_data_models You can also import core.stdc.config witch defines both c_long and c_ulong. -- Mike Wey
Re: Interfacing with c and platform dependent sizes
On 26.02.2011 17:06, Mike Wey wrote: On 02/26/2011 11:49 AM, Jacob Carlborg wrote: On 2011-02-26 01:28, simendsjo wrote: C is not my strong side, so I'm having some problems wrapping some code. I found a couple of sources on this: 1) http://www.digitalmars.com/d/2.0/htomodule.html 2) http://www.digitalmars.com/d/2.0/interfaceToC.html 1) C's long is the same as D's int. long long is long 2) C 32bit's long long is D's long, C 64 bits long is D's long. So.. A long in C is the same as the platform size? And long long doesn't exist in 64 bit? In general you can follow the table at http://www.digitalmars.com/d/2.0/htomodule.html But when it comes to "long" in C you have to be careful. On 32bit platforms a C "long" will be 32bit long. But on 64bit platforms it depends of what data model is used. To simplify things: * On Windows 64bit a C "long" will be 32bit long * On Posix 64bit a C "long" will be 64bit long. What you can do is to create an alias called "c_long" and "c_ulong", something like this: version (D_LP64) { version (Windows) { alias int c_long; alias uint c_ulong; } else { alias long c_long; alias ulong c_ulong; } } else { alias int c_long; alias uint c_ulong; } To read more about data models: http://en.wikipedia.org/wiki/64-bit#Specific_C-language_data_models You can also import core.stdc.config witch defines both c_long and c_ulong. Thanks for all the answers. Is something like this correct? version(X86_64) { version(Windows) { version = LLP64; } else version(Posix) { version = LP64; } else { static assert(0); } version(LLP64) { alias short c_short; alias ushort c_ushort; alias int c_int; alias uint c_uint; alias int c_long; alias uint c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else version(LP64) { alias short c_short; alias ushort c_ushort; alias int c_int; alias uint c_uint; alias long c_long; alias ulong c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else version(ILP64) { alias short c_short; alias ushort c_ushort; alias long c_int; alias ulong c_uint; alias long c_long; alias ulong c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else version(SILP64) { alias long c_short; alias ulong c_ushort; alias long c_int; alias ulong c_uint; alias long c_long; alias ulong c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else { static assert(0); } } else version(X86) { alias short c_short; alias ushort c_ushort; alias int c_int; alias uint c_uint; alias int c_long; alias uint c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias uint c_size_t; } else { static assert(0); }
Re: Interfacing with c and platform dependent sizes
On 02/26/2011 05:58 PM, simendsjo wrote: On 26.02.2011 17:06, Mike Wey wrote: On 02/26/2011 11:49 AM, Jacob Carlborg wrote: On 2011-02-26 01:28, simendsjo wrote: C is not my strong side, so I'm having some problems wrapping some code. I found a couple of sources on this: 1) http://www.digitalmars.com/d/2.0/htomodule.html 2) http://www.digitalmars.com/d/2.0/interfaceToC.html 1) C's long is the same as D's int. long long is long 2) C 32bit's long long is D's long, C 64 bits long is D's long. So.. A long in C is the same as the platform size? And long long doesn't exist in 64 bit? In general you can follow the table at http://www.digitalmars.com/d/2.0/htomodule.html But when it comes to "long" in C you have to be careful. On 32bit platforms a C "long" will be 32bit long. But on 64bit platforms it depends of what data model is used. To simplify things: * On Windows 64bit a C "long" will be 32bit long * On Posix 64bit a C "long" will be 64bit long. What you can do is to create an alias called "c_long" and "c_ulong", something like this: version (D_LP64) { version (Windows) { alias int c_long; alias uint c_ulong; } else { alias long c_long; alias ulong c_ulong; } } else { alias int c_long; alias uint c_ulong; } To read more about data models: http://en.wikipedia.org/wiki/64-bit#Specific_C-language_data_models You can also import core.stdc.config witch defines both c_long and c_ulong. Thanks for all the answers. Is something like this correct? version(X86_64) { version(Windows) { version = LLP64; } else version(Posix) { version = LP64; } else { static assert(0); } version(LLP64) { alias short c_short; alias ushort c_ushort; alias int c_int; alias uint c_uint; alias int c_long; alias uint c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else version(LP64) { alias short c_short; alias ushort c_ushort; alias int c_int; alias uint c_uint; alias long c_long; alias ulong c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else version(ILP64) { alias short c_short; alias ushort c_ushort; alias long c_int; alias ulong c_uint; alias long c_long; alias ulong c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else version(SILP64) { alias long c_short; alias ulong c_ushort; alias long c_int; alias ulong c_uint; alias long c_long; alias ulong c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else { static assert(0); } } else version(X86) { alias short c_short; alias ushort c_ushort; alias int c_int; alias uint c_uint; alias int c_long; alias uint c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias uint c_size_t; } else { static assert(0); } The aliases look correct, but i don't think you'll need ILP64 or SILP64 any time soon. -- Mike Wey
Re: Interfacing with c and platform dependent sizes
On 2/25/2011 7:24 PM, Steven Schveighoffer wrote: BTW, I think long long is a gnu extension, it's not standard C (I don't think long long exists in Visual C for instance). I'm pretty sure it's standard as of C99 (though not yet for C++; that's coming with C++0x). MSVC does indeed support it.
Re: Interfacing with c and platform dependent sizes
On 2011-02-26 17:06, Mike Wey wrote: On 02/26/2011 11:49 AM, Jacob Carlborg wrote: On 2011-02-26 01:28, simendsjo wrote: C is not my strong side, so I'm having some problems wrapping some code. I found a couple of sources on this: 1) http://www.digitalmars.com/d/2.0/htomodule.html 2) http://www.digitalmars.com/d/2.0/interfaceToC.html 1) C's long is the same as D's int. long long is long 2) C 32bit's long long is D's long, C 64 bits long is D's long. So.. A long in C is the same as the platform size? And long long doesn't exist in 64 bit? In general you can follow the table at http://www.digitalmars.com/d/2.0/htomodule.html But when it comes to "long" in C you have to be careful. On 32bit platforms a C "long" will be 32bit long. But on 64bit platforms it depends of what data model is used. To simplify things: * On Windows 64bit a C "long" will be 32bit long * On Posix 64bit a C "long" will be 64bit long. What you can do is to create an alias called "c_long" and "c_ulong", something like this: version (D_LP64) { version (Windows) { alias int c_long; alias uint c_ulong; } else { alias long c_long; alias ulong c_ulong; } } else { alias int c_long; alias uint c_ulong; } To read more about data models: http://en.wikipedia.org/wiki/64-bit#Specific_C-language_data_models You can also import core.stdc.config witch defines both c_long and c_ulong. Yeah, I always forgets that module in druntime, even though it's based on Tango where I do remember it. -- /Jacob Carlborg
Re: Interfacing with c and platform dependent sizes
On 2011-02-26 23:02, Mike Wey wrote: On 02/26/2011 05:58 PM, simendsjo wrote: On 26.02.2011 17:06, Mike Wey wrote: On 02/26/2011 11:49 AM, Jacob Carlborg wrote: On 2011-02-26 01:28, simendsjo wrote: C is not my strong side, so I'm having some problems wrapping some code. I found a couple of sources on this: 1) http://www.digitalmars.com/d/2.0/htomodule.html 2) http://www.digitalmars.com/d/2.0/interfaceToC.html 1) C's long is the same as D's int. long long is long 2) C 32bit's long long is D's long, C 64 bits long is D's long. So.. A long in C is the same as the platform size? And long long doesn't exist in 64 bit? In general you can follow the table at http://www.digitalmars.com/d/2.0/htomodule.html But when it comes to "long" in C you have to be careful. On 32bit platforms a C "long" will be 32bit long. But on 64bit platforms it depends of what data model is used. To simplify things: * On Windows 64bit a C "long" will be 32bit long * On Posix 64bit a C "long" will be 64bit long. What you can do is to create an alias called "c_long" and "c_ulong", something like this: version (D_LP64) { version (Windows) { alias int c_long; alias uint c_ulong; } else { alias long c_long; alias ulong c_ulong; } } else { alias int c_long; alias uint c_ulong; } To read more about data models: http://en.wikipedia.org/wiki/64-bit#Specific_C-language_data_models You can also import core.stdc.config witch defines both c_long and c_ulong. Thanks for all the answers. Is something like this correct? version(X86_64) { version(Windows) { version = LLP64; } else version(Posix) { version = LP64; } else { static assert(0); } version(LLP64) { alias short c_short; alias ushort c_ushort; alias int c_int; alias uint c_uint; alias int c_long; alias uint c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else version(LP64) { alias short c_short; alias ushort c_ushort; alias int c_int; alias uint c_uint; alias long c_long; alias ulong c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else version(ILP64) { alias short c_short; alias ushort c_ushort; alias long c_int; alias ulong c_uint; alias long c_long; alias ulong c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else version(SILP64) { alias long c_short; alias ulong c_ushort; alias long c_int; alias ulong c_uint; alias long c_long; alias ulong c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else { static assert(0); } } else version(X86) { alias short c_short; alias ushort c_ushort; alias int c_int; alias uint c_uint; alias int c_long; alias uint c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias uint c_size_t; } else { static assert(0); } The aliases look correct, but i don't think you'll need ILP64 or SILP64 any time soon. I agree. -- /Jacob Carlborg
Re: Interfacing with c and platform dependent sizes
On 2011-02-26 17:58, simendsjo wrote: On 26.02.2011 17:06, Mike Wey wrote: On 02/26/2011 11:49 AM, Jacob Carlborg wrote: On 2011-02-26 01:28, simendsjo wrote: C is not my strong side, so I'm having some problems wrapping some code. I found a couple of sources on this: 1) http://www.digitalmars.com/d/2.0/htomodule.html 2) http://www.digitalmars.com/d/2.0/interfaceToC.html 1) C's long is the same as D's int. long long is long 2) C 32bit's long long is D's long, C 64 bits long is D's long. So.. A long in C is the same as the platform size? And long long doesn't exist in 64 bit? In general you can follow the table at http://www.digitalmars.com/d/2.0/htomodule.html But when it comes to "long" in C you have to be careful. On 32bit platforms a C "long" will be 32bit long. But on 64bit platforms it depends of what data model is used. To simplify things: * On Windows 64bit a C "long" will be 32bit long * On Posix 64bit a C "long" will be 64bit long. What you can do is to create an alias called "c_long" and "c_ulong", something like this: version (D_LP64) { version (Windows) { alias int c_long; alias uint c_ulong; } else { alias long c_long; alias ulong c_ulong; } } else { alias int c_long; alias uint c_ulong; } To read more about data models: http://en.wikipedia.org/wiki/64-bit#Specific_C-language_data_models You can also import core.stdc.config witch defines both c_long and c_ulong. Thanks for all the answers. Is something like this correct? version(X86_64) { version(Windows) { version = LLP64; } else version(Posix) { version = LP64; } else { static assert(0); } version(LLP64) { alias short c_short; alias ushort c_ushort; alias int c_int; alias uint c_uint; alias int c_long; alias uint c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else version(LP64) { alias short c_short; alias ushort c_ushort; alias int c_int; alias uint c_uint; alias long c_long; alias ulong c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else version(ILP64) { alias short c_short; alias ushort c_ushort; alias long c_int; alias ulong c_uint; alias long c_long; alias ulong c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else version(SILP64) { alias long c_short; alias ulong c_ushort; alias long c_int; alias ulong c_uint; alias long c_long; alias ulong c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else { static assert(0); } } else version(X86) { alias short c_short; alias ushort c_ushort; alias int c_int; alias uint c_uint; alias int c_long; alias uint c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias uint c_size_t; } else { static assert(0); } I suggest you use core.stdc.config instead, I forgot it existed. BTW size_t already exists in D (defined in the object module) and it will be the same as size_t in C. -- /Jacob Carlborg
Re: Interfacing with c and platform dependent sizes
On Sat, 26 Feb 2011 22:24:52 -0500, Bekenn wrote: On 2/25/2011 7:24 PM, Steven Schveighoffer wrote: BTW, I think long long is a gnu extension, it's not standard C (I don't think long long exists in Visual C for instance). I'm pretty sure it's standard as of C99 (though not yet for C++; that's coming with C++0x). MSVC does indeed support it. OK, I was not aware, my C book is from college, and I went to college in 94. I always thought in Windows you had to use something like __int64. -Steve
Re: Interfacing with c and platform dependent sizes
On 27.02.2011 11:43, Jacob Carlborg wrote: On 2011-02-26 17:58, simendsjo wrote: On 26.02.2011 17:06, Mike Wey wrote: On 02/26/2011 11:49 AM, Jacob Carlborg wrote: On 2011-02-26 01:28, simendsjo wrote: C is not my strong side, so I'm having some problems wrapping some code. I found a couple of sources on this: 1) http://www.digitalmars.com/d/2.0/htomodule.html 2) http://www.digitalmars.com/d/2.0/interfaceToC.html 1) C's long is the same as D's int. long long is long 2) C 32bit's long long is D's long, C 64 bits long is D's long. So.. A long in C is the same as the platform size? And long long doesn't exist in 64 bit? In general you can follow the table at http://www.digitalmars.com/d/2.0/htomodule.html But when it comes to "long" in C you have to be careful. On 32bit platforms a C "long" will be 32bit long. But on 64bit platforms it depends of what data model is used. To simplify things: * On Windows 64bit a C "long" will be 32bit long * On Posix 64bit a C "long" will be 64bit long. What you can do is to create an alias called "c_long" and "c_ulong", something like this: version (D_LP64) { version (Windows) { alias int c_long; alias uint c_ulong; } else { alias long c_long; alias ulong c_ulong; } } else { alias int c_long; alias uint c_ulong; } To read more about data models: http://en.wikipedia.org/wiki/64-bit#Specific_C-language_data_models You can also import core.stdc.config witch defines both c_long and c_ulong. Thanks for all the answers. Is something like this correct? version(X86_64) { version(Windows) { version = LLP64; } else version(Posix) { version = LP64; } else { static assert(0); } version(LLP64) { alias short c_short; alias ushort c_ushort; alias int c_int; alias uint c_uint; alias int c_long; alias uint c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else version(LP64) { alias short c_short; alias ushort c_ushort; alias int c_int; alias uint c_uint; alias long c_long; alias ulong c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else version(ILP64) { alias short c_short; alias ushort c_ushort; alias long c_int; alias ulong c_uint; alias long c_long; alias ulong c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else version(SILP64) { alias long c_short; alias ulong c_ushort; alias long c_int; alias ulong c_uint; alias long c_long; alias ulong c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias ulong c_size_t; } else { static assert(0); } } else version(X86) { alias short c_short; alias ushort c_ushort; alias int c_int; alias uint c_uint; alias int c_long; alias uint c_ulong; alias long c_longlong; alias ulong c_ulonglong; alias uint c_size_t; } else { static assert(0); } I suggest you use core.stdc.config instead, I forgot it existed. BTW size_t already exists in D (defined in the object module) and it will be the same as size_t in C. Ok. Thanks.
Re: Interfacing with c and platform dependent sizes
On Sunday 27 February 2011 05:41:49 Steven Schveighoffer wrote: > On Sat, 26 Feb 2011 22:24:52 -0500, Bekenn wrote: > > On 2/25/2011 7:24 PM, Steven Schveighoffer wrote: > >> BTW, I think long long is a gnu extension, it's not standard C (I don't > >> think long long exists in Visual C for instance). > > > > I'm pretty sure it's standard as of C99 (though not yet for C++; that's > > coming with C++0x). MSVC does indeed support it. > > OK, I was not aware, my C book is from college, and I went to college in > 94. > > I always thought in Windows you had to use something like __int64. That would be the smart thing to do, but long long does exist. IHMO, if you don't care about the size of an integral type in C/C++, you use int. Otherwise, you use a type that specifices it's size and is _guaranteed_ to be that size on all systems. Using types like long and long long is just asking for it. Fortunately, D specifies the size of its types, so that isn't a problem. - Jonathan M Davis
Re: Using a delegate when interfacing with C
On Saturday, 5 July 2014 at 22:18:56 UTC, Marco Cosentino wrote: auto client = *(cast(ClientImplementation*) data); Try just auto client = cast(ClientImplementation) data; and this.setProcessCallback(callback, cast(void *) &this); setProcessCallback(callback, cast(void*) this); Can somebody help me in figuring out why this happens? The reason is a class this in D is already a pointer (just a hidden one) so when you do &this in a class, it is like a ClientImplementation** in C - a pointer to a (temporary) pointer. So by the time the callback runs, it is pointing to nonsense. In general, remember any class reference in D is already equivalent to a pointer in C or C++ and can be casted straight to void* without needing to take its address.
Re: Using a delegate when interfacing with C
On Saturday, 5 July 2014 at 22:28:48 UTC, Adam D. Ruppe wrote: In general, remember any class reference in D is already equivalent to a pointer in C or C++ and can be casted straight to void* without needing to take its address. Thanks Adam, you're a life saver ;). It works like a charme.
Re: Using a delegate when interfacing with C
Hey Adam, an interesting aspect of what I'd like to achieve is to use compile-time reflection to generate the wrapper functions for all the delegates (there are ~ 10). The pattern is like what I presented eariler and in addition to that there are some delegates which have no return type (void). I managed to write a template like this (D is awesome): alias ProcessDelegate = int delegate(NFrames nframes); import std.traits; private template CallbackWrapper(alias T) if(isDelegate!T) { extern(C) static auto wrapper(ParameterTypeTuple!T params, void * data) { auto client = cast(ClientImplementation) data; return mixin("client." ~ __traits(identifier, T) ~ "(params)"); } } void setProcessDelegate(ProcessDelegate deleg) { processDelegate = deleg; setProcessCallback( & CallbackWrapper!(processDelegate).wrapper, cast(void *) this); }
How to use inheritance when interfacing with C++ classes?
I would like to interface with a C++ library called [FLTK](https://www.fltk.org/). I'm trying to implement the binding for the classes based to what I've read [here](https://dlang.org/spec/cpp_interface.html#classes) but it seems that It doesn't work as expected for me. I want to implement the "abstract" class "Fl_Widget" and the class "Fl_Group" which inherits from the "Fl_Widget". I will put a part of the code as there is no reason to put the whole code and make the post unnecessarily big. If in any case however, you need the whole reference: [Fl_Widget](https://fltk.gitlab.io/fltk/classFl__Widget.html) and [Fl_Group](https://fltk.gitlab.io/fltk/classFl__Group.html). Here is the code: ``` extern(C++) { abstract class Fl_Widget { void _clear_fullscreen(); void _set_fullscreen(); } class Fl_Group : Fl_Widget { ref Fl_Widget*_ddfdesign_kludge(); void add(ref Fl_Widget); void add(Fl_Widget*o); } } ``` Normally this should work but the "Fl_Group" class makes in bug and I'm getting the following error message: ``` Linking... /usr/bin/ld: .dub/build/application-debug-linux.posix-x86_64-dmd_v2.098.0-A4E26D206D34B9B9CA1A0366B3CE0F2C/dfltk.o:(.data._D4test8Fl_Group6__vtblZ+0x0): undefined reference to `Fl_Widget::_clear_fullscreen()' /usr/bin/ld: .dub/build/application-debug-linux.posix-x86_64-dmd_v2.098.0-A4E26D206D34B9B9CA1A0366B3CE0F2C/dfltk.o:(.data._D4test8Fl_Group6__vtblZ+0x8): undefined reference to `Fl_Widget::_set_fullscreen()' /usr/bin/ld: .dub/build/application-debug-linux.posix-x86_64-dmd_v2.098.0-A4E26D206D34B9B9CA1A0366B3CE0F2C/dfltk.o:(.data._D4test8Fl_Group6__vtblZ+0x10): undefined reference to `Fl_Group::_ddfdesign_kludge()' /usr/bin/ld: .dub/build/application-debug-linux.posix-x86_64-dmd_v2.098.0-A4E26D206D34B9B9CA1A0366B3CE0F2C/dfltk.o:(.data._D4test8Fl_Group6__vtblZ+0x18): undefined reference to `Fl_Group::add(Fl_Widget*&)' /usr/bin/ld: .dub/build/application-debug-linux.posix-x86_64-dmd_v2.098.0-A4E26D206D34B9B9CA1A0366B3CE0F2C/dfltk.o:(.data._D4test8Fl_Group6__vtblZ+0x20): undefined reference to `Fl_Group::add(Fl_Widget**)' collect2: error: ld returned 1 exit status Error: linker exited with status 1 ``` Anyone has an idea?
Re: Interfacing with C++ std::shared_ptr and std::unique_ptr
On Wednesday, 10 June 2020 at 06:43:24 UTC, Andre Pany wrote: Also, the C++ classes make use of templates. Is it still possible to call these classes from D? It should be, I did something similar and it worked. But it was quite some time ago so I don't remember exact situation and any details. However you still be out of luck if the types you are trying to use is present in header only, since there is simply nothing to link with, so now you have to port whole template to D, or make dummy wrapper in C++ that forces the compiler to emit those symbols. Same with ctor/dtors, if you have a class that is only used in some executable and not present in any of a .lib/.a form you're stuck. This is especially annoying with destructors because it renders the whole thing unusable without helper libraries that does new/delete in order to get the damn symbols emitted in object files to be able to link.
Re: Interfacing with C++ std::shared_ptr and std::unique_ptr
On Wednesday, 10 June 2020 at 06:43:24 UTC, Andre Pany wrote: Hi, I would like to interface with the library https://github.com/NTNU-IHB/FMI4cpp and have following class definitions in the header file: ``` c++ namespace fmi4cpp { template class fmu_base { public: const std::string guid() const { return get_model_description()->guid; } const std::string model_name() const { return get_model_description()->model_name; } virtual std::shared_ptr get_model_description() const = 0; }; templateme_fmu> class fmu_provider : public virtual fmu_base { public: virtual bool supports_cs() const = 0; virtual bool supports_me() const = 0; virtual std::unique_ptr as_cs_fmu() const = 0; virtual std::unique_ptr as_me_fmu() const = 0; }; ``` While unique_ptr is already available in drunime library core.stdcpp.memory, shared_ptr is missing. Does someone already have translated shared_ptr? Also, the C++ classes make use of templates. Is it still possible to call these classes from D? Kind regards Andre Depending on your needs, it might be trivial. We use this, and it works accross all 3 platforms: https://github.com/bpfkorea/agora/blob/ddd65e2fc3975d9c14ad36bcf28e5cd32de08945/source/scpd/Cpp.d#L38-L64 As mentioned, you will need to have the instantiation done on the C++ side, but that's true for any template. Feel free to ask on slack #cpp-interop.
Re: Interfacing with C++ std::shared_ptr and std::unique_ptr
On Wednesday, 10 June 2020 at 08:31:47 UTC, Mathias LANG wrote: On Wednesday, 10 June 2020 at 06:43:24 UTC, Andre Pany wrote: [...] Depending on your needs, it might be trivial. We use this, and it works accross all 3 platforms: https://github.com/bpfkorea/agora/blob/ddd65e2fc3975d9c14ad36bcf28e5cd32de08945/source/scpd/Cpp.d#L38-L64 As mentioned, you will need to have the instantiation done on the C++ side, but that's true for any template. Feel free to ask on slack #cpp-interop. Thanks for all the answers. I will have a look. Kind regards Andre
Re: How to use inheritance when interfacing with C++ classes?
On Thursday, 9 December 2021 at 19:05:08 UTC, rempas wrote: Anyone has an idea? The referenced methods like Fl_Widget::_clear_fullscreen are implemented directly in the header, so the D code also needs the implementation, because it is not included in the compiled library. Methods, which are not virtual in C++, also have to be marked final in D, because C++ and D use a different default.
Re: How to use inheritance when interfacing with C++ classes?
On Thursday, 9 December 2021 at 21:35:14 UTC, Tim wrote: The referenced methods like Fl_Widget::_clear_fullscreen are implemented directly in the header, so the D code also needs the implementation, because it is not included in the compiled library. What is funny about that is that I looked an the official class reference and copy pasted the code from here but I also looked at the header files and saw what you said but for some reason it completely slipped from my head... Methods, which are not virtual in C++, also have to be marked final in D, because C++ and D use a different default. Is this a must or just good practices?
Re: How to use inheritance when interfacing with C++ classes?
On Friday, 10 December 2021 at 12:46:07 UTC, rempas wrote: On Thursday, 9 December 2021 at 21:35:14 UTC, Tim wrote: Methods, which are not virtual in C++, also have to be marked final in D, because C++ and D use a different default. Is this a must or just good practices? All virtual methods have to match exactly including order. If a virtual method is missing or added, then calling this or a later virtual method could call the wrong method or generate a segmentation fault. Non-virtual methods have to be marked final in D, but can also be removed.
Re: How to use inheritance when interfacing with C++ classes?
On Friday, 10 December 2021 at 16:42:33 UTC, Tim wrote: All virtual methods have to match exactly including order. If a virtual method is missing or added, then calling this or a later virtual method could call the wrong method or generate a segmentation fault. Non-virtual methods have to be marked final in D, but can also be removed. Great info! I'll have everything in mind! Thanks a lot and have an amazing day!!!
Interfacing with C - calling member function of D struct from C?
Hello! If I have a D struct like: struct Foo { int bar; void addToBar(int what) { bar += what; } } How would I call `addToBar` from C code? Would I need to put the `addToBar` function outside of the struct and mark it as `extern (C)` and in normal D code take advantage of UFCS or is there some magic C incantation? I've scoured the forums and other places for anything about this but couldn't find any information whatsoever... so yeah. (or my Google-fu is terrible) Thanks!
Re: Interfacing with C - calling member function of D struct from C?
On Sunday, 25 June 2017 at 02:05:35 UTC, unleashy wrote: How would I call `addToBar` from C code? You don't. Instead write it like: struct Foo { int bar; } extern(C) void addToBar(Foo* foo, int what) { foo.bar += what; } Then define it in C the same way and you call it the normal way from C. But from D, you can UFCS call it: Foo* foo = new Foo(); foo.addToBar(5); // cool though I'd prolly just call it from D the same way you do from C too.
Re: Interfacing with C - calling member function of D struct from C?
On Sunday, 25 June 2017 at 02:09:53 UTC, Adam D. Ruppe wrote: On Sunday, 25 June 2017 at 02:05:35 UTC, unleashy wrote: How would I call `addToBar` from C code? You don't. Instead write it like: struct Foo { int bar; } extern(C) void addToBar(Foo* foo, int what) { foo.bar += what; } Then define it in C the same way and you call it the normal way from C. But from D, you can UFCS call it: Foo* foo = new Foo(); foo.addToBar(5); // cool though I'd prolly just call it from D the same way you do from C too. Thank you, this is what I suspected :)
how to handle memory ownership when interfacing with C/C++ via internal pointers
Short version: I have a struct A* aptr allocated in C/C++ with an internal pointer aptr->ptr (say a double*) I want to store a reference x (say double[]) in D to aptr only through aptr->ptr, not through aptr directly as it's inconvenient in my use case. How do I achieve that, so that when x goes out of scope, some deallocator for aptr will be called ? Long version: suppose I have C++ code: struct A{ double*ptr; A(size_t n){ptr=(double*)malloc(n);} ~A(){free(ptr);} }; and a D wrapper around it: extern(C){struct A; A*A_new(size_t n); void A_delete(A*a); double*A_ptr(A*a);} I want to use it as follows: double[] get_x(size_t n){ return A_new(n).A_ptr[0..n]; } void main(){ double[]x=get_x(n); // do something with x; } It's trivial to handle this via a class wrapper: class A2{ A*a; this(size_t n){a=A_new(n);} ~this(){A_delete(n);} double*ptr(){return A_ptr(a);} } double[] get_x(size_t n){ auto a2=new A2(n); return a2.ptr; //this doesn't help much though, A2 will go out of scope when this function exits. } but I don't want to maintain objects of class A2 around, just double[] slices as above. Is there some magic involving core.memory.addRoot,addRange (etc) I can use so that a2 stays alive as long as x stays alive? (in which case when x goes out of scope, 'a2' will too, and will call A_delete). Thanks
Interfacing with C libs: weeding through C/C++ macros and such in header files
Hello all! So while I have a decent grasp on D, I've been having trouble figuring out specific projects that I could do in D, so I thought I'd maybe find a little C or C++ library I could transfer over to D. I decided to make my life easier and look for something that's just a single header file, and while that does make things easier there are a TON of macros and inline functions that it almost seems ridiculous and it's somewhat overwhelming. Example without code; for some reason a macro is defined for the stdlib functions `malloc`, `realloc`, and `free`. Maybe it's just because I don't have any pro experience with C or C++, but that seems a bit excessive. Or I could just be dumb. Example with code (because I need help figuring out how whether I even need this or not): #ifndef RS_API #ifdef RS_NOINLINE /* GCC version 3.1 required for the no inline attribute. */ #if RS_GCC_VERSION > 30100 #define RS_API static __attribute__((noinline)) #elif defined(_MSC_VER) #define RS_API static __declspec(noinline) #else #define RS_API static #endif #elif RS_C99 #define RS_API static inline #elif defined(__GNUC__) #define RS_API static __inline__ #elif defined(_MSC_VER) #define RS_API static __forceinline #else #define RS_API static #endif #endif I understand what it's doing, but do I really any of this with D? And then there's this inline function #define RS_DATA_SIZE(f, s, input) \ do { \ if (rs_is_heap(input)) \ f(s, input->heap.buffer, rs_heap_len(input)); \ else\ f(s, input->stack.buffer, rs_stack_len(input)); \ } while (0) so yea. There's a little over 300 lines of preprocessor stuff. My question is how you all determine what to carry over from C libs in terms of preprocessor stuff. I imagine most useful values everyone just makes an enum for, and structs and unions are kept. Thanks for any help you give!
Re: how to handle memory ownership when interfacing with C/C++ via internal pointers
On Thursday, 10 October 2013 at 23:02:29 UTC, Timothee Cour wrote: Short version: I have a struct A* aptr allocated in C/C++ with an internal pointer aptr->ptr (say a double*) I want to store a reference x (say double[]) in D to aptr only through aptr->ptr, not through aptr directly as it's inconvenient in my use case. How do I achieve that, so that when x goes out of scope, some deallocator for aptr will be called ? Long version: suppose I have C++ code: struct A{ double*ptr; A(size_t n){ptr=(double*)malloc(n);} ~A(){free(ptr);} }; and a D wrapper around it: extern(C){struct A; A*A_new(size_t n); void A_delete(A*a); double*A_ptr(A*a);} I want to use it as follows: double[] get_x(size_t n){ return A_new(n).A_ptr[0..n]; } void main(){ double[]x=get_x(n); // do something with x; } It's trivial to handle this via a class wrapper: class A2{ A*a; this(size_t n){a=A_new(n);} ~this(){A_delete(n);} double*ptr(){return A_ptr(a);} } double[] get_x(size_t n){ auto a2=new A2(n); return a2.ptr; //this doesn't help much though, A2 will go out of scope when this function exits. } but I don't want to maintain objects of class A2 around, just double[] slices as above. Is there some magic involving core.memory.addRoot,addRange (etc) I can use so that a2 stays alive as long as x stays alive? (in which case when x goes out of scope, 'a2' will too, and will call A_delete). Thanks Ping? Is anything above unclear? here are more details (in a simplified setting): say, I have an image class D_image which has fields: ubyte* ptr //pointer to memory uint[2] size; I'd like to interface with, say, a swig-wrapped opencv C++ image class Swig_image, so that when an object d_image:D_image goes out of scope (and its pointer ptr also goes out of scope), (with d_image constructed from an object swig_image of type Swig_image), then swig_image will also go out of scope. again, this can be done by adding a field to D_image (say of type void* to make it work with any source), buy I'm wondering whether this can be achieved without adding this field, with some GC magic associating a pointer (ptr) to another pointer (cast(void*) swig_image). This would make interfacing with C++ libs much easier as there would be no bookkeeping in user code.
Re: Interfacing with C libs: weeding through C/C++ macros and such in header files
On Sunday, 13 January 2019 at 22:40:57 UTC, Alec Stewart wrote: Example without code; for some reason a macro is defined for the stdlib functions `malloc`, `realloc`, and `free`. Maybe it's just because I don't have any pro experience with C or C++, but that seems a bit excessive. Or I could just be dumb. These three are members of the standard library in D. https://dlang.org/phobos/core_memory.html Example with code (because I need help figuring out how whether I even need this or not): #ifndef RS_API #ifdef RS_NOINLINE /* GCC version 3.1 required for the no inline attribute. */ #if RS_GCC_VERSION > 30100 #define RS_API static __attribute__((noinline)) #elif defined(_MSC_VER) #define RS_API static __declspec(noinline) #else #define RS_API static #endif #elif RS_C99 #define RS_API static inline #elif defined(__GNUC__) #define RS_API static __inline__ #elif defined(_MSC_VER) #define RS_API static __forceinline #else #define RS_API static #endif #endif I understand what it's doing, but do I really any of this with D? And then there's this inline function #define RS_DATA_SIZE(f, s, input) \ do { \ if (rs_is_heap(input)) \ f(s, input->heap.buffer, rs_heap_len(input)); \ else\ f(s, input->stack.buffer, rs_stack_len(input)); \ } while (0) so yea. There's a little over 300 lines of preprocessor stuff. My question is how you all determine what to carry over from C libs in terms of preprocessor stuff. I imagine most useful values everyone just makes an enum for, and structs and unions are kept. Thanks for any help you give! At first, I would suggest to try out some automatic converters, which are written by the community: https://wiki.dlang.org/Bindings#Binding_generators especially dstep and dpp I had some ambivalent experience with the procedure of converting C --> D, but there is C code out there, which behaves very well in this respect... So, generally, I pursued the tactics of automatic conversion trying to compile rewriting missing parts. Also, if there is a possibility to compile the C/C++ library, you could provide the interface only to the functions you need. Then, you reuse the existent code directly and interface the library by declaring the interfaces as extern in your D sources. https://dlang.org/spec/attribute.html#linkage
Re: Interfacing with C libs: weeding through C/C++ macros and such in header files
On Sunday, 13 January 2019 at 23:23:50 UTC, Alex wrote: These three are members of the standard library in D. https://dlang.org/phobos/core_memory.html Ah, yea that's way easier. At first, I would suggest to try out some automatic converters, which are written by the community: https://wiki.dlang.org/Bindings#Binding_generators especially dstep and dpp That would make it easier because there's a lot of preprocessor stuff that ends up being circular references if I use `enum` or `const`. Also, if there is a possibility to compile the C/C++ library, you could provide the interface only to the functions you need. Then, you reuse the existent code directly and interface the library by declaring the interfaces as extern in your D sources. https://dlang.org/spec/attribute.html#linkage That would also be easier. :P Thanks!
Re: Interfacing with C libs: weeding through C/C++ macros and such in header files
On Sunday, 13 January 2019 at 22:40:57 UTC, Alec Stewart wrote: Example without code; for some reason a macro is defined for the stdlib functions `malloc`, `realloc`, and `free`. Maybe it's just because I don't have any pro experience with C or C++, but that seems a bit excessive. Or I could just be dumb. Generally this is done to allow the compile-time configuration of memory allcoators. Back in my C days I had a little memory module that tracked total allocated and unallocated bytes and logged a few stats to a file at shutdown. I used macros to switch between it and the default stdlib calls. I understand what it's doing, but do I really any of this with D? No. And then there's this inline function #define RS_DATA_SIZE(f, s, input) \ do { \ if (rs_is_heap(input)) \ f(s, input->heap.buffer, rs_heap_len(input)); \ else\ f(s, input->stack.buffer, rs_stack_len(input)); \ } while (0) Generally, this sort of thing can be moved into a D function or template if it's repeated in several places. Without the do...while, of course. And in case you're unfamiliar with its purpose here: https://stackoverflow.com/questions/154136/why-use-apparently-meaningless-do-while-and-if-else-statements-in-macros