Re: Hipreme's Tip of of the day #09 - Using D shared libraries with dub
On Monday, 4 September 2023 at 23:57:03 UTC, Hipreme wrote: Hello again! -- As of some requests in DConf, I'll post here some things related (or not) to dub recipes. Since there is so many ways to build D and dub is quite the main way, I'll try to show other uncommon ways to use it, this is more recommended to bigger projects since the standard one is enough for most. [...] Thanks for these Hipreme. I always enjoy reading them.
Re: dub does not correctly link on Macbook Pro 2019 (intel)
On Saturday, 19 August 2023 at 22:53:53 UTC, Sergey wrote: On Saturday, 19 August 2023 at 21:35:25 UTC, Alexander wrote: Completely new to D, and when trying to setup the toolchain, Could you please specify the versions of macOS and DMD? Probably DMD is broken for macOS - could you try to use LDC? Maybe this thread is relative to the problem: https://github.com/ldc-developers/ldc/issues/3864 I think that thread is where I originally found the bandaid I described: https://github.com/ldc-developers/ldc/issues/3864#issuecomment-963304679
Re: dub does not correctly link on Macbook Pro 2019 (intel)
On Saturday, 19 August 2023 at 21:35:25 UTC, Alexander wrote: Completely new to D, and when trying to setup the toolchain, DMD seems to work fine, but dub is running into linker issues. On my Intel iMac I have to set `MACOSX_DEPLOYMENT_TARGET`: ``` MACOSX_DEPLOYMENT_TARGET=11 dub run ``` That puts a bandaid on the linker issues. I haven’t yet set aside time to report it as an issue.
Re: Mir-algorithm tutorial?
On Saturday, 19 August 2023 at 08:59:40 UTC, Ferhat Kurtulmuş wrote: On Saturday, 19 August 2023 at 01:44:16 UTC, Kyle Ingraham wrote: On Friday, 18 August 2023 at 12:14:45 UTC, Ferhat Kurtulmuş wrote: I think the main problem is the mir libraries won't get updates since Ilya recently said that he was not an open source developer anymore. That’s unfortunate for D but hopefully beneficial for Ilya. Was it said somewhere publicly where I can read more on it? https://forum.dlang.org/post/u7r1i8$rn7$1...@digitalmars.com Much appreciated Ferhat.
Re: Mir-algorithm tutorial?
On Friday, 18 August 2023 at 12:14:45 UTC, Ferhat Kurtulmuş wrote: I think the main problem is the mir libraries won't get updates since Ilya recently said that he was not an open source developer anymore. That’s unfortunate for D but hopefully beneficial for Ilya. Was it said somewhere publicly where I can read more on it?
Re: Linker Error with Template Function
On Saturday, 1 October 2022 at 21:18:05 UTC, Ali Çehreli wrote: On 10/1/22 11:15, Kyle Ingraham wrote: > storing structs as > `void*` in a wrapper struct with information about their module and > identifier saved elsewhere. Perhaps unrelated but that part reminded me of the following discussion: https://forum.dlang.org/post/tfbn10$19nv$1...@digitalmars.com Ali Thanks for this Ali. I found it useful to see another way to solve this problem. Seems like it would be great to have a `Type` type that can store a type at compile-time for use at run-time.
Re: Linker Error with Template Function
On Tuesday, 13 September 2022 at 08:43:45 UTC, Nick Treleaven wrote: On Tuesday, 13 September 2022 at 03:00:17 UTC, Kyle Ingraham wrote: Any suggestions for being able to call one function for any instance given but maintain flexible return types? Not sure if it helps, but you can define final methods in an interface, which can call virtual interface methods: ```d interface PathConverter { string getValue(); final T toD(T)() { import std.conv : to; return to!T(getValue()); } } ``` Not tested as AFK. Thanks for the suggestion Nick. I solved this by storing structs as `void*` in a wrapper struct with information about their module and identifier saved elsewhere. I use that information to setup casts to the appropriate type then call `toD`. That way I can call the same method for functions that return different types and store disparate structs to the same wrapper struct. The wrapper struct gets used in function signatures.
Re: Linker Error with Template Function
On Tuesday, 13 September 2022 at 01:46:14 UTC, Paul Backus wrote: On Tuesday, 13 September 2022 at 00:57:58 UTC, Kyle Ingraham wrote: I am writing a library where I would like to be able to store instances of a type of class to an associative array for later usage. Each class stored has to implement a function as part of the required interface. The argument given is always the same type but the return value should be flexible. I solved this with an interface: ```d interface PathConverter { T toD(T)(const string value) @safe; } ``` https://dlang.org/spec/template.html#limitations Templates cannot be used to add non-static fields or virtual functions to classes or interfaces. You *should* get an error from the compiler for trying to do this, instead of just a linker error somewhere else down the line, but either way it's not going to work. You'll have to find another solution. Thanks for the spec help Paul. I must've skirted around the compiler somehow. This is a minimal example that triggers the linker error: ```d interface PathConverter { T toD(T)(string value); } class NumberConverter(T) : PathConverter { T toD(T)(string value) { import std.conv : to; return to!T(value); } } alias IntConverter = NumberConverter!int; void main() { PathConverter[string] allConverters; allConverters["int"] = new IntConverter; int converted = allConverters["int"].toD!int("9"); } ``` Any suggestions for being able to call one function for any instance given but maintain flexible return types?
Linker Error with Template Function
I am writing a library where I would like to be able to store instances of a type of class to an associative array for later usage. Each class stored has to implement a function as part of the required interface. The argument given is always the same type but the return value should be flexible. I solved this with an interface: ```d interface PathConverter { T toD(T)(const string value) @safe; } ``` That interface lets me type the associative array and any other part of the library that needs to use implementers of that interface e.g. ```d PathConverter[string] converters; ``` The problem I'm running into is that when compile the library I receive the following error during linking: ``` error LNK2019: unresolved external symbol _D3app13PathConverter__T3toDTAyaZQjMFNfxAyaZQp referenced in function _D3app14TypedURLRouter__T10setHandlerTPFNfC4vibe4http6server17HTTPServerRequestCQBlQBjQBh18HTTPServerResponseAyaZvZQDmMFEQDaQCy6common10HTTPMethodQBlQEhZ__T9__lambda4TQEvTQDoTASQGt16PathCaptureGroupZQBrMFNfQGiQFaQBlZv fatal error LNK1120: 1 unresolved externals Error: linker exited with status 1120 ``` The call is within a delegate to a function that returns a class instance from the associative array. At runtime I fill the associative array. The call looks like this: ```d tailArgs[i] = getPathConverter("id string").toD!(Parameters!(handler)[i])("string to convert"); ``` Am I running into this error because the linker can't find the instantiation of the template method? How would I give the linker the information it needs? Is there a better way to have an interface with flexible return values?
Re: Is there a way to
On Sunday, 11 September 2022 at 00:56:39 UTC, Adam D Ruppe wrote: On Sunday, 11 September 2022 at 00:32:18 UTC, Kyle Ingraham wrote: I can't use default parameters because I want to be able to call the delegate with arguments extracted from a URL path at runtime Some kind of wrapper might not only be your best option, it might be your only option. Your delegate would be like string callWith(string[][string] webArgs) and you can generate a wrapper to convert arguments and call the original function. I'm mucking about with a custom router for vibe-d and trying to setup the ability for handlers to have different parameter signatures. I'd be surprised if vibe doesn't already have this built in, my web frameworks have since before vibe was born. (my implementation btw does the wrapper thing like described above) Thanks for the wrapper suggestion Adam. I tried that out and got the functionality that I wanted. I wrap the handler in a delegate that has the signature I need. vibe-d does have a way to achieve something similar but I'm working on a router that does a bit more path validation before calling a handler.
Re: Is there a way to
On Sunday, 11 September 2022 at 00:04:55 UTC, Adam D Ruppe wrote: On Saturday, 10 September 2022 at 23:37:30 UTC, Kyle Ingraham wrote: How can I write a type that is strict for the first two parameters but tolerant of any other parameter following those? That's not a type per se, but you can assign wrapper at the assignment thing. Like your_delegate = (a,b) => func_with_three_args(a, b, "some default"); that kind of thing. if you have a delegate in an object, you can use a property setter to accept more things and wrap it like that. My problem is that I would like to store a reference to that delegate in a struct for later use: ```d struct MyStruct { MyDelegate myDelegate; } ``` I can't use default parameters because I want to be able to call the delegate with arguments extracted from a URL path at runtime. I'm mucking about with a custom router for vibe-d and trying to setup the ability for handlers to have different parameter signatures.
Is there a way to
Is there a way to write a delegate type as being specific for some parameters and tolerant of anything for others? For example, I can specify this type: ```d alias MyDelegateType = void delegate(string name, int age); ``` It would be compatible with a pointer to this function converted to a delegate: ```d void someFunc(string name, int age) { // } ``` That type would not work for this function though: ```d void anotherFunc(string name, int age, string location) { // } ``` How can I write a type that is strict for the first two parameters but tolerant of any other parameter following those?
Re: A look inside "filter" function defintion
On Tuesday, 2 August 2022 at 12:39:41 UTC, pascal111 wrote: but I'm still stuck. Do you have a down-to-earth example for beginners to understand this concept? I often go back to this post when writing templates: https://dlang.org/blog/2020/07/31/the-abcs-of-templates-in-d/ It helped me when I was first trying to understand them.
Re: How to make a new dub subpackage? [Answered]
Thanks for the writeup. How are you using this functionality?
Re: Payload Details with std.net.curl:post
On Sunday, 28 November 2021 at 07:27:35 UTC, ikod wrote: On Sunday, 28 November 2021 at 01:06:45 UTC, Kyle Ingraham wrote: On Saturday, 27 November 2021 at 22:18:48 UTC, ikod wrote: On Saturday, 27 November 2021 at 20:31:16 UTC, Kyle Ingraham Hi Kyle, ``` object.Exception@C:\Users\Kyle Ingraham\AppData\Local\dub\packages\requests-2.0.2\requests\source\requests\streams.d(890): ssl connect failed: certificate verify failed ``` I checked the issues page for `hunt-http` and saw that there were similar reports there from Windows users (I have not verified them myself). I did not try `vibe-http` because the callback interface in the docs wasn't one that grabbed me. Do you have tips on why I might be getting that exception? I'm guessing I need to point `requests` at a trust store. Yes, trust store location can be the problem. I hope you checked this readme sections: [windows-ssl-notes](https://github.com/ikod/dlang-requests#windows-ssl-notes) and [ssl-settings](https://github.com/ikod/dlang-requests#ssl-settings). It is difficult to answer without having more details, but I recently fixed a bug that could lead to a similar problem on 32-bit systems (regardless of OS). If this is your case, then you can try to use the latest commit from the github. Anyway, it would be nice if you create an issue on github and post more details there, so that I can try to reproduce the problem. I had read those sections but couldn't figure out which combination of certificates and function calls would make a difference for my URL. I found https://pki.goog/repository/ which has links to all certificates relevant to Google URLs. I worked my way down the certificate chain and the call that worked was: ```D auto rq = Request(); rq.sslSetCaCert(r"gtsr1.pem"); ``` That certificate is for one of Google's root CAs but not the root of the certificate chain. With that combination my request worked and the payload was delivered successfully. I was also able to see the payload that had been sent in my request which was my motivation for starting this thread in the first place. I think my trouble here was mostly due to my limited familiarity with SSL verification. I ended up using a CA certificate and the method made available was `sslSetCaCert`. A bit obvious when I look back. I had not used it at first because it was referenced as being needed for vibe.d and when perusing `requests` I thought that it wasn't being called for my setup. Glad to have a working setup now. Thank you ikod for stopping by and asking about my experiences outside of `std.net.curl`. P.S. `openssl s_client -connect :443` was useful for viewing the certificate chain.
Re: Payload Details with std.net.curl:post
On Saturday, 27 November 2021 at 22:18:48 UTC, ikod wrote: On Saturday, 27 November 2021 at 20:31:16 UTC, Kyle Ingraham wrote: On Saturday, 27 November 2021 at 19:21:28 UTC, frame wrote: On Saturday, 27 November 2021 at 17:41:55 UTC, Kyle Ingraham wrote: I was afraid of that. Thank you for clarifying. I’ve tried other clients but they all seem to have trouble verifying HTTPS connections. Which clients did you try, and what the troubles they have? Hi ikod. I tried `requests` on Windows 10 (Build 19042) and got the following exception: ``` object.Exception@C:\Users\Kyle Ingraham\AppData\Local\dub\packages\requests-2.0.2\requests\source\requests\streams.d(890): ssl connect failed: certificate verify failed ``` I checked the issues page for `hunt-http` and saw that there were similar reports there from Windows users (I have not verified them myself). I did not try `vibe-http` because the callback interface in the docs wasn't one that grabbed me. I would have dug further into the solution for the `requests` exception as I like the interface it provides but I was eager to power through the OAuth bit of my prototyping so that I could experiment with the Google Photos API. Do you have tips on why I might be getting that exception? I'm guessing I need to point `requests` at a trust store.
Re: Payload Details with std.net.curl:post
On Saturday, 27 November 2021 at 19:21:28 UTC, frame wrote: On Saturday, 27 November 2021 at 17:41:55 UTC, Kyle Ingraham wrote: Is there a way to see that information? Google's API does not seem to provide much more than a status code as to the reason for the failure. No, and it's a shame that we cannot use CurlOption.debugfunction because the Curl struct on HTTP is private and the only way to set this option is to use a raw Curl instance. You are on your own working with onReceive(), setPostData() and std.uri.urlEncode() to encode your post data. I was afraid of that. Thank you for clarifying. I’ve tried other clients but they all seem to have trouble verifying HTTPS connections. I’ll see about debugging with curl outside of D or go the manual route like you suggested.
Payload Details with std.net.curl:post
Happy Saturday everyone. I am using `std.net.curl:post` to request an OAuth access token from a Google API. Initially I was getting a 400 status code back but could not tell why. I used the `verbose` option on `HTTP()` to get more details: ```D char[] tokenResponse; auto connection = HTTP(); connection.verbose = true; try { tokenResponse = post ( tokenRequestEndpoint, ["code": incomingCode, "redirect_uri": tokenRequestRedirectUrl, "grant_type": "authorization_code", "code_verifier": to!string(codeVerifier), "client_id": clientId, "client_secret": clientSecret], connection ); } catch(HTTPStatusException e) { writefln("Token request failed - Status code: %d - Message: %s\n", e.status, e.msg); return 1; } ``` That `verbose` option gets me a detailed log but I cannot see the payload of my request nor that of the response: ``` * Trying 172.217.165.10:443... * TCP_NODELAY set * Connected to www.googleapis.com (172.217.165.10) port 443 (#0) POST /oauth2/v4/token HTTP/1.1 Host: www.googleapis.com User-Agent: Phobos-std.net.curl/2.098 (libcurl/7.68.0) Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Content-Length: 16 Content-Type: application/x-www-form-urlencoded * We are completely uploaded and fine * Mark bundle as not supporting multiuse < HTTP/1.1 400 Bad Request < Content-Type: application/json; charset=utf-8 < Vary: X-Origin < Vary: Referer < Date: Sat, 27 Nov 2021 14:24:45 GMT < Server: scaffolding on HTTPServer2 < Cache-Control: private < X-XSS-Protection: 0 < X-Frame-Options: SAMEORIGIN < X-Content-Type-Options: nosniff < Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43" < Accept-Ranges: none < Vary: Origin,Accept-Encoding < Transfer-Encoding: chunked < * Connection #0 to host www.googleapis.com left intact ``` Is there a way to see that information? Google's API does not seem to provide much more than a status code as to the reason for the failure.
Re: regarding what seems (to me) unnecessary casts on integer expressions
On Saturday, 5 June 2021 at 00:24:01 UTC, someone wrote: On Saturday, 5 June 2021 at 00:24:01 UTC, someone wrote: ? 0 : cast(ushort)(this.pintBottom1 - 1); } It looks like you’re being caught by D’s arithmetic conversions: https://dlang.org/spec/type.html#usual-arithmetic-conversions “If the signed type is larger than the unsigned type, the unsigned type is converted to the signed type.” Your pint variables are ushorts but the 1 you subtract is an int literal so the result gets promoted to an int. Also, I don’t believe there is an unambiguous way to write a ushort literal: https://dlang.org/spec/type.html#basic-data-types You should be ok with “u” if the function’s return is ushort. The compiler should be able to figure it out from there. I’m hoping I’m not wrong there as I haven’t tried it myself.
Re: Does is(f == function) work?
On Tuesday, 9 March 2021 at 11:58:45 UTC, Andrey Zherikov wrote: On Tuesday, 9 March 2021 at 02:57:46 UTC, Adam D. Ruppe wrote: try is(typeof(f) == function) it is kinda weird but that's the trick Thanks! Should it work for in this case as well? alias f = (){}; writeln(typeof(f).stringof);// prints "void function() pure nothrow @nogc @safe" writeln(is(typeof(f) == function)); // prints "false" Does Unqual help here?: https://dlang.org/phobos/std_traits.html#Unqual
Re: Compile-Time Function Parameters That Aren't Types?
On Wednesday, 24 February 2021 at 20:15:08 UTC, Ali Çehreli wrote: On 2/23/21 7:52 PM, Kyle Ingraham wrote: Where would one find information on this There are Point and Polygon struct templates on the following page where one can pick e.g. the dimension (e.g. three dimensional space) by a size_t template parameter. http://ddili.org/ders/d.en/templates_more.html#ix_templates_more.value%20template%20parameter Ali Thank you very much Ali. This is another great example. Your book has been most helpful!
Re: Compile-Time Function Parameters That Aren't Types?
On Wednesday, 24 February 2021 at 06:18:02 UTC, H. S. Teoh wrote: Usually it's when there's a decision that needs to be made at compile-time (or desirable to be made at compile-time for whatever reason). For example, if there are two very different branches of code that should run depending on the value of parameter, and user code is expected to want only one or the other code path, so fixing the code path at compile-time may be advantageous. D's operator overloading is one example of this. It takes a compile-time string containing the operator, which lets the implementor choose whether to implement multiple operator overloads separately, or grouped together in a common implementation. E.g.: Thank you for the additional clarification with a new example. Compile-time parameters are indeed a powerful tool.
Re: Compile-Time Function Parameters That Aren't Types?
On Wednesday, 24 February 2021 at 03:57:37 UTC, Adam D. Ruppe wrote: On Wednesday, 24 February 2021 at 03:52:57 UTC, Kyle Ingraham wrote: The part that got my attention was `bool isBGR`. I was under the impression that compile-time or template parameters were only for types. No, you can pass almost anything to them. https://dlang.org/spec/template.html#template_value_parameter Much appreciated. This is exactly what I wanted to take a look at. and other surrounding sections Why would one write a function this way? To specialize on information known at compile time. It will also call functions as-needed to get that value all at compile time. That brings it all together. Types aren't the only thing one would want to use to specialize. Thank you for the explanation. I'm making my way in from interpreted languages so templates are a still unfamiliar way to solve problems.
Compile-Time Function Parameters That Aren't Types?
I was reading the code for the DCV library and came across this function: https://github.com/libmir/dcv/blob/master/source/dcv/imgproc/color.d#L128 Here is a shortened form: [return type] rgbbgr2gray(bool isBGR, V)([run-time parameters]){[implementation]} and an example call: rgbbgr2gray!(true, [a type])([run-time arguments]) The part that got my attention was `bool isBGR`. I was under the impression that compile-time or template parameters were only for types. Where would one find information on this in the D spec? Why would one write a function this way?
Re: Problem Computing Dot Product with mir
On Monday, 22 February 2021 at 07:14:26 UTC, 9il wrote: On Sunday, 21 February 2021 at 16:18:05 UTC, Kyle Ingraham wrote: I am trying to convert sRGB pixel values to XYZ with mir using the following guide: http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html [...] mir-glas is deprecated experimental project. It is worth use mir-blas or lubeck instead. There is also naming issue. In the classic BLAS naming dot refers a function that accept two 1D vectors. Your suggestion worked beautifully. I went with lubeck. I don't know how I missed it seeing that it is right there in the Dlang tour. Thank you for writing such useful libraries. Final code ended up being: import std.stdio; import kaleidic.lubeck: mtimes; import mir.ndslice: as, byDim, fuse, map, sliced; void main() { auto rgbToXyz = [0.4124564, 0.3575761, 0.1804375, 0.2126729, 0.7151522, 0.0721750, 0.0193339, 0.1191920, 0.9503041] .as!double .sliced(3, 3); ubyte[] rgbPixels = [255, 0, 0, 0, 255, 0, 0, 0, 255, 120, 120, 120]; auto xyzPixels = rgbPixels // convert input array elements to double - lazy .as!double // create a slice-shell over the input array .sliced(2, 2, 3) // normalize pixel channels to range [0, 1] .map!(chnl => chnl / 255.0) // sRGB inverse compand .map!(chnl => chnl <= 0.04045 ? chnl / 12.92 : ((chnl + 0.055) / 1.055) ^^ 2.4) // linear RGB to XYZ // iterator by x and y over pixels (3rd dimension) .byDim!(0, 1) // same as .pack!1 // dot product of each pixel with conversion matrix .map!(pixel => mtimes(rgbToXyz, pixel)) // join iterator values into a matrix .fuse; xyzPixels.writeln; xyzPixels.shape.writeln; }
Problem Computing Dot Product with mir
I am trying to convert sRGB pixel values to XYZ with mir using the following guide: http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html My problem is that I cannot figure out how to calculate a dot product using mir. Here is my code: import std.stdio; import mir.glas.l1 : dot; import mir.ndslice; void main() { auto rgbToXyz = [0.4124564, 0.3575761, 0.1804375, 0.2126729, 0.7151522, 0.0721750, 0.0193339, 0.1191920, 0.9503041] .as!double .sliced(3, 3); alias reduceDot = reduce!"a * b"; auto pixels = [255, 0, 0, 0, 255, 0, 0, 0, 255, 120, 120, 120] // convert input array elements to double - lazy .as!double // create a slice-shell over the input array .sliced(2, 2, 3) // normalize to range [0, 1] .map!(p => p / 255.0) // sRGB inverse compand .map!(V => V <= 0.04045 ? V / 12.92 : ((V + 0.055) / 1.055) ^^ 2.4) // linear RGB to XYZ // iterator over pixel values - 3rd dimension .pack!1 // dot product of pixel value with conversion matrix .map!(a => reduceDot(rgbToXyz, a)); //.map!(a => dot(rgbToXyz, a)); writeln(pixels); writeln(pixels.shape); } In the last step I am trying to take each pixel value from my 2x2 'image' and compute a dot product of it and the conversion matrix rgbToXyz. I have tried reduce and that results in: Error: cannot implicitly convert expression nonInlinedNaryFun(seed, ls()) of type Slice!(VmapIterator!(double*, LeftOp!("*", double)), 2LU, cast(mir_slice_kind)2) to Slice!(double*, 2LU, cast(mir_slice_kind)2) I have also tried dot from mir.glas.l1: Error: template mir.glas.l1.dot cannot deduce function from argument types !()(Slice!(double*, 2LU, cast(mir_slice_kind)2), Slice!(MapIterator!(int*, pipe), 1LU, cast(mir_slice_kind)2)) I was expecting the conversion matrix (3x3) dotted with the pixel (3x1) to produce another pixel (3x1). What am I doing wrong here?
Re: struct constructor with rvalue param of same struct type
I’m sorry that this isn’t a solution to your problem but your code caught my attention. What is your snippet supposed to do?
Re: Simple BeamUI project won't link
On Friday, 18 December 2020 at 19:14:25 UTC, Daren Scot Wilson wrote: So maybe beamui isn't ready for the real world. It's a one-off personal tool for image processing, maybe will go up on Github, so I don't need anything super-solid or well established. OTOH, if it's too much on the WIP side with lots of loose ends, it might be more work than my free time allows. At least, beamui appears to be more workable than dlangui which seems to have fallen away. Did you find a GUI library to work with? I'm in the same boat as you working on a tool for image processing in my free time.
Re: D Bindings for C Opaque Pointers
On Thursday, 3 December 2020 at 01:19:05 UTC, bachmeier wrote: On Thursday, 3 December 2020 at 00:30:06 UTC, Kyle Ingraham wrote: What did I do wrong in constructing the bindings? If it helps the library provides a function called EdsRelease for cleaning-up allocated objects. Is the management of pointers between D and C the issue? Please forgive me if I've mangled that concept. Not an answer to your question, but the "idiomatic" approach is to not write bindings yourself. dstep generates bindings: https://github.com/jacob-carlborg/dstep dpp lets you include C header files directly: https://github.com/atilaneves/dpp Thanks for the suggestions here. I had no idea that these tools existed. Now that I've gotten my feet wet with doing it manually it'll be interesting to compare results with those from automation. I'm all for it they can take some of the heavy lifting away.
Re: D Bindings for C Opaque Pointers
On Thursday, 3 December 2020 at 00:58:20 UTC, Paul Backus wrote: On Thursday, 3 December 2020 at 00:30:06 UTC, Kyle Ingraham wrote: // EDSDKTypes.h typedef struct __EdsObject* EdsBaseRef; typedef EdsBaseRef EdsCameraListRef; // [...] // edsdk.d struct EdsBaseRef; alias EdsBaseRef EdsCameraListRef; You've dropped a level of indirection here. In the C header, EdsBaseRef is a pointer, but in your D code, it is an opaque struct. The correct way to translate these C declarations into D is: struct __EdsObject; alias EdsBaseRef = __EdsObject*; alias EdsCameraListRef = EdsBaseRef; Note that unlike C, D does not allow us to refer to an incomplete type without first declaring it. That did it. The binding works without issue now. Thanks a ton for the direction. I'll keep that distinction between C and D in mind as I go forward. It's been night and day between D and C++. I struggled for a while getting this work going in C++ but was firmly blocked by CMake. D and dub have been champs for ease of use.
D Bindings for C Opaque Pointers
Hello all. I am new to D and loving the experience so far. I am trying to make use of a C library from Canon that provides a header and a pre-compiled binary containing implementations of declarations found in the header. I used the excellent guide at https://www.gamedev.net/articles/programming/general-and-gameplay-programming/binding-d-to-c-r3122/ to get started and so far I can initialize the library and embed it within my D application. So far so great! Where I am running into problems is creating D bindings for this function declaration: // EDSDK.h EdsError EDSAPI EdsGetCameraList(EdsCameraListRef* outCameraListRef); // If accepts a pointer to EdsCameraListRef that is declared as: // EDSDKTypes.h typedef struct __EdsObject* EdsBaseRef; typedef EdsBaseRef EdsCameraListRef; // From my reading I learned that EdsCameraListRef is an alias of an alias for an opaque pointer. It allowed the library writers to declare an object for use that the end-user would not have access to the implementation of. These are the D bindings I created: // edsdk.d struct EdsBaseRef; alias EdsBaseRef EdsCameraListRef; alias uint EdsUInt32; extern (System): EdsError EdsGetCameraList(EdsCameraListRef*); EdsError EdsGetChildCount(EdsBaseRef*, EdsUInt32*); EdsUInt32 EdsRelease(EdsBaseRef*); // Calling the functions using the bindings and the following code results in invalid pointer errors however (reported from the library): // camera_list.d import edsdk; class CameraList { private EdsCameraListRef* list; private EdsUInt32 _count = 0; this() { // Returns EDS_ERR_INVALID_POINTER EdsGetCameraList(list); // Returns EDS_ERR_INVALID_HANDLE EdsGetChildCount(list, &_count); } ~this() { EdsRelease(list); } final uint count() { return cast(uint) _count; } } // What did I do wrong in constructing the bindings? If it helps the library provides a function called EdsRelease for cleaning-up allocated objects. Is the management of pointers between D and C the issue? Please forgive me if I've mangled that concept.