Re: Ethan: About your wpf/C# and D integration
On Monday, 12 August 2019 at 13:08:17 UTC, Bert wrote: What I'd like to do is write the business end of apps in D and use C# for the gui(with possibly wpf hosting a D gui window in some cases for performance of graphics). I want to leverage D's meta programming to write efficient oop structures. Exactly what I'm doing. Client and server backends are written in D. Binderoo generates the C# <==> D interfaces. There's a few traps I haven't worked out fully yet. Structs are a sticking point. I have them byte mapped exactly, but. Well. Here's an example: std.uuid.UUID [ Serializable ] [ StructLayout( LayoutKind.Explicit, Pack = 8 ) ] public struct UUID { public enum Version : int { unknown = -1, timeBased = 1, dceSecurity = 2, nameBasedMD5 = 3, randomNumberBased = 4, nameBasedSHA1 = 5, } // public enum Variant : int { ncs = 0, rfc4122 = 1, microsoft = 2, future = 3, } // // // Methods // public void swap( ref std.uuid.UUID rhs ) { binderoointernal.FP.std_uuid_UUID_swap3( ref this, ref rhs ); } // public ulong toHash( ) { return binderoointernal.FP.std_uuid_UUID_toHash4( ref this ); } // public string toString( ) { return new SliceString( binderoointernal.FP.std_uuid_UUID_toString5( ref this ) ).Data; } // // // Properties // public std.uuid.UUID.Variant variant { get { return binderoointernal.FP.std_uuid_UUID_variant1( ref this ); } } // public bool empty { get { return binderoointernal.FP.std_uuid_UUID_empty0( ref this ); } } // public std.uuid.UUID.Version uuidVersion { get { return binderoointernal.FP.std_uuid_UUID_uuidVersion2( ref this ); } } // //Ridiculous fixed array preservation code for data of length 16 [ FieldOffset( 0 ) ] private byte var_data_elem0; [ FieldOffset( 1 ) ] private byte var_data_elem1; [ FieldOffset( 2 ) ] private byte var_data_elem2; [ FieldOffset( 3 ) ] private byte var_data_elem3; [ FieldOffset( 4 ) ] private byte var_data_elem4; [ FieldOffset( 5 ) ] private byte var_data_elem5; [ FieldOffset( 6 ) ] private byte var_data_elem6; [ FieldOffset( 7 ) ] private byte var_data_elem7; [ FieldOffset( 8 ) ] private byte var_data_elem8; [ FieldOffset( 9 ) ] private byte var_data_elem9; [ FieldOffset( 10 ) ] private byte var_data_elem10; [ FieldOffset( 11 ) ] private byte var_data_elem11; [ FieldOffset( 12 ) ] private byte var_data_elem12; [ FieldOffset( 13 ) ] private byte var_data_elem13; [ FieldOffset( 14 ) ] private byte var_data_elem14; [ FieldOffset( 15 ) ] private byte var_data_elem15; //Ridiculous fixed array preservation code for ulongs of length 2 [ FieldOffset( 0 ) ] private ulong var_ulongs_elem0; [ FieldOffset( 8 ) ] private ulong var_ulongs_elem1; // } C#'s types and D's don't exactly match (ESPECIALLY if you run on Windows vs any other platform). If I want to match the C ABI that D adheres to, I have to go full paranoid and define an explicit pack. Then there's things like strings. I've still not come up with a way that I'm satisfied with to deal with allocated data being passed between both languages and not being garbage collected. You could take the "GC pin" route. But I'm not satisfied with that for parameter passing. There's no guarantees a user will or won't keep a string on either side of the language divide. I'm still pondering on that one. I'm taking a convention of array.dup in my D code whenever assigning a slice in a C# exposed function. Full solution to be determined. For it to work well the amount of boilerplate has to be minimized and the interfacing between D and C# also has to be minimal. Absolutely. The original goal of Binderoo was to make C++ and D interoperation and hot reloading seamless. Since I left Remedy, that goal has now become to make language barriers irrelevant for any supported langua
Re: Private variables accessible from outside class
On Thursday, 8 August 2019 at 15:51:45 UTC, Drobet wrote: I'm having a weird issue, where after defining my classes variables as private https://dlang.org/spec/attribute.html Section 8.4.2 of the spec reads: Symbols with private visibility can only be accessed from within the same module. Private member functions are implicitly final and cannot be overridden. If you were to put that Vector3 class in another module and import it, you'll find that private works as you expect. You'll find this ability very useful when you start using Uniform Function Call Syntax in your code. https://tour.dlang.org/tour/en/gems/uniform-function-call-syntax-ufcs
Re: Emulating DLL
On Tuesday, 19 March 2019 at 19:50:15 UTC, Craig wrote: For example, with windows I could simply compile to a dll then extract the code, or just use LoadLibrary and it effectively does all the work(steps 1 & 2 & 3). LoadLibrary performs steps 1 and part of step 2. The DllMain function of a library is called separately by Windows for each thread in your system, which is where the bulk of step 2 is handled. Step 3 isn't handled at all by LoadLibrary, and is instead entirely up to you to deal with via the GetProcAddress function. If you want DLLs to operate in that step 1-2-3 manner, then the compiler can generate a static library that handles that all for you. But, as you might expect, that removes the hot reloading capability as that is all handled before WinMain is entered. If you expect hot reloading to work without effort, you're going to have to compile your DLLs with -betterC. The D Runtime is not yet in a standalone DLL (unless I've missed an announcement over the last couple of months). Each DLL you build will require the D runtime to be embedded. Things get really tricky from there. If you ever use your DLL for more than calling functions with basic types, or value aggregates (structs) containing basic types, then be aware that without -betterC that there is potential for the moduleinfo and typeinfo systems to go a bit screwy. Especially once druntime lives in its own DLL, as druntime expects those systems to be initialised once at startup. POSIX libraries will have the same issues, but I have nod had a need to investigate further over the last few months. LoadLibrary is not portable though and seems excessive to do something that should be rather simple unless there is something I'm missing that has to be done that is complex. LoadLibrary is the equivalent to dlopen on POSIX systems, with one very important difference: Windows does not provide lazy symbol evaluation. As such, extra work is required to handle that. The average usecase is covered by the mentioned static lib, but any hot reloading is handled in a custom manner by every Windows codebase you'll encounter. The static lib I mention, in fact, redirects every cross-DLL call to a jump table. And cross-DLL data sharing gets hairy in Windows. Function parameters aren't a problem, but Windows explicitly disallows thread local variables to cross the DLL boundary for example (even if you expose it for export and perform a symbol lookup, it won't work and you'll get garbage back). As I said, it's not a simple thing by any means. My work has attempted to hide all that complexity by boiling it all down to "include these headers/modules, link this lib, and get on with life". If you find the resulting code too complex (and I freely admit that I haven't got the integration in to as foolproof a manner as I am aiming for) then very definitely read through the presentations to get a clear idea of why something that should be so simple really isn't.
Re: WTF! new in class is static?!?!
On Thursday, 7 June 2018 at 21:07:26 UTC, DigitalDesigns wrote: assert(b1.a == b2.a)!! The spec isn't clear on this but it uses the same rules as struct field initialisation, ie it's defined once and copied to each instance on creation. https://dlang.org/spec/struct.html#default_struct_init