Re: Writing Postgresql extension in D
On Friday, 16 November 2018 at 02:18:11 UTC, Ranjan wrote: On Thursday, 15 November 2018 at 17:03:55 UTC, Andrea Fontana wrote: On Thursday, 15 November 2018 at 13:05:59 UTC, Ranjan wrote: This is my first time on the Dlang forum. I like the language but my usecase is a bit different. I want to write Postgresql extension in D. Currently extension can be written in C or C linked languages. Has anyone done this or can point me to some code. Thanks Did you read this: https://dlang.org/spec/interfaceToC.html ? Andrea Yes, but it's not useful, in Postgesql extension C code needs to call D, without GarbageCollection. I am able to do this in RustLang but I am not sure how to in D, as it has a GC. Looking for examples from the community. Thanks There is -betterC [1] compiler flag that allows one to code without the D runtime and create programs that depend only on the C runtime, so there is no GC - and no GC related functionality also. You probably want to try this route for creating the extension, as it will be simpler if you know C and the Postgres API. 1. https://dlang.org/spec/betterc.html
Re: Writing Postgresql extension in D
On 16/11/2018 3:18 PM, Ranjan wrote: On Thursday, 15 November 2018 at 17:03:55 UTC, Andrea Fontana wrote: On Thursday, 15 November 2018 at 13:05:59 UTC, Ranjan wrote: This is my first time on the Dlang forum. I like the language but my usecase is a bit different. I want to write Postgresql extension in D. Currently extension can be written in C or C linked languages. Has anyone done this or can point me to some code. Thanks Did you read this: https://dlang.org/spec/interfaceToC.html ? Andrea Yes, but it's not useful, in Postgesql extension C code needs to call D, without GarbageCollection. I am able to do this in RustLang but I am not sure how to in D, as it has a GC. Looking for examples from the community. Thanks There isn't anything special you need to learn. As long as you don't mutate anything you receive via the GC or send any GC owned memory outside of D, you'll have an easy time of it.
Re: Writing Postgresql extension in D
On Thursday, 15 November 2018 at 17:03:55 UTC, Andrea Fontana wrote: On Thursday, 15 November 2018 at 13:05:59 UTC, Ranjan wrote: This is my first time on the Dlang forum. I like the language but my usecase is a bit different. I want to write Postgresql extension in D. Currently extension can be written in C or C linked languages. Has anyone done this or can point me to some code. Thanks Did you read this: https://dlang.org/spec/interfaceToC.html ? Andrea Yes, but it's not useful, in Postgesql extension C code needs to call D, without GarbageCollection. I am able to do this in RustLang but I am not sure how to in D, as it has a GC. Looking for examples from the community. Thanks
Re: Where is there documentation on how to write inline asm?
Well, for anyone who is tangling with similar mysteries, I finally got something to work the way I wanted it to. Thank you for the help, Adam and kinke! The first "x" argument was stored in R8. The second "y" argument was stored in RDX. The invisible return value pointer was stored in RCX. Here's what I was hoping to accomplish. The multiply function returns the low bits of the product in the `low` attribute of the struct and the high bits in the `high` attribute of the struct. The divide function returns the quotient in `low` and the remainder in `high`. struct Result { ulong low; ulong high; } Result unsignedMultiply(ulong x, ulong y) { version(D_InlineAsm_X86_64) asm { naked; mov RAX, R8; mul RDX; mov qword ptr [RCX], RAX; mov qword ptr [RCX + 8], RDX; ret; } } Result unsignedDivide(ulong x, ulong y) { version(D_InlineAsm_X86_64) asm { naked; mov RAX, R8; mov R9, RDX; mov RDX, 0; div R9; mov qword ptr [RCX], RAX; mov qword ptr [RCX + 8], RDX; ret; } }
Re: what are the rules for @nogc and @safe attributes inference?
On 11/15/18 4:09 PM, Adam D. Ruppe wrote: On Thursday, 15 November 2018 at 21:00:48 UTC, ikod wrote: what are the rules for @nogc inference? It attempts it if and only if it is a template. Well, the general "rule" is, if it's code that must be available to the compiler when it's called, then it will be inferred. Examples of code that must be processed every time it's used: 1. Template functions 2. auto-returning functions 3. functions inside templates (like member functions of a templated struct) 4. Inner functions There may be others I didn't think of. Everything else must be manually attributed. The reasoning is that the function may be stubbed in a .di file, and in that case, attribute inference wouldn't be possible. -Steve
Re: Where is there documentation on how to write inline asm?
Ah, I've got something working! It's not exactly what I wanted, but it's good enough for now. Instead of using an invisible output pointer, the output pointer is passed in explicitly. struct Result { ulong low; ulong high; } void retTest(Result* result) { version(D_InlineAsm_X86_64) asm { naked; mov [RAX + 0], 0x80; mov [RAX + 8], 0xff; ret; } }
Re: Where is there documentation on how to write inline asm?
On Thursday, 15 November 2018 at 21:48:46 UTC, kinke wrote: The MS docs are complete IIRC. The pointer to the pre-allocated result of your 16-bytes struct is passed in RCX. If unsure, just reverse-engineer what you need: type it down in normal D and analyze the generated assembly. You can even do so online via run.dlang.io (https://run.dlang.io/is/rhsDBF); just select LDC and add `-mtriple=x86_64-pc-windows-msvc` to generate Win64 assembly. Note that run.dlang.io displays AT asm, not the Intel one. You can use LDC offline via `-output-s -x86-asm-syntax=intel` to generate a .s file with Intel syntax. When I tested by writing to the pointer given by RCX, the program didn't crash but I did get different values every time and never the ones I wanted.
Re: Where is there documentation on how to write inline asm?
On Thursday, 15 November 2018 at 21:32:10 UTC, pineapple wrote: On the less positive side: I still have no clue how to return my 16-byte struct. The Microsoft x64 ABI documentation I've seen so far explains how return values of 8 bytes and fewer work, but haven't explained how larger return values work. The obvious answer of "RAX or EAX contains a pointer" is either not working or my asm is wrong. (The latter is certainly a possibility.) The MS docs are complete IIRC. The pointer to the pre-allocated result of your 16-bytes struct is passed in RCX. If unsure, just reverse-engineer what you need: type it down in normal D and analyze the generated assembly. You can even do so online via run.dlang.io (https://run.dlang.io/is/rhsDBF); just select LDC and add `-mtriple=x86_64-pc-windows-msvc` to generate Win64 assembly. Note that run.dlang.io displays AT asm, not the Intel one. You can use LDC offline via `-output-s -x86-asm-syntax=intel` to generate a .s file with Intel syntax.
Re: Where is there documentation on how to write inline asm?
On Thursday, 15 November 2018 at 21:12:39 UTC, Adam D. Ruppe wrote: On Thursday, 15 November 2018 at 21:07:51 UTC, pineapple wrote: Is there a way to access this pointer? It is passed as.. I think the final argument to the function. (unless it is the first, do a quick test to find out). Also, the calling convention documentation there doesn't mention anything about 64-bit targets, are 64-bit registers just not used? It uses the C rules there, so look up the 64 bit C abi. I think this is accurate https://msdn.microsoft.com/en-us/library/ms235286.aspx On the positive side: I see now how to return a 64-bit value from a function in Windows x64! And I understand how the arguments are coming in. This is very helpful. On the less positive side: I still have no clue how to return my 16-byte struct. The Microsoft x64 ABI documentation I've seen so far explains how return values of 8 bytes and fewer work, but haven't explained how larger return values work. The obvious answer of "RAX or EAX contains a pointer" is either not working or my asm is wrong. (The latter is certainly a possibility.) // Returns 128 (0x80) ulong retTest() { version(D_InlineAsm_X86_64) asm { naked; mov RAX, 0x80; ret; } } // Crashes struct Result { ulong low; ulong high; } Result retTest() { version(D_InlineAsm_X86_64) asm { naked; mov [RAX + 0], 0x80; mov [RAX + 8], 0x80; ret; } } // Also crashes struct Result { ulong low; ulong high; } Result retTest() { version(D_InlineAsm_X86_64) asm { naked; mov [R9 + 0], 0x80; mov [R9 + 8], 0x80; ret; } }
Re: Where is there documentation on how to write inline asm?
On Thursday, 15 November 2018 at 21:07:51 UTC, pineapple wrote: Is there a way to access this pointer? It is passed as.. I think the final argument to the function. (unless it is the first, do a quick test to find out). Also, the calling convention documentation there doesn't mention anything about 64-bit targets, are 64-bit registers just not used? It uses the C rules there, so look up the 64 bit C abi. I think this is accurate https://msdn.microsoft.com/en-us/library/ms235286.aspx
Re: what are the rules for @nogc and @safe attributes inference?
On Thursday, 15 November 2018 at 21:00:48 UTC, ikod wrote: what are the rules for @nogc inference? It attempts it if and only if it is a template.
Re: Where is there documentation on how to write inline asm?
On Thursday, 15 November 2018 at 21:00:10 UTC, Adam D. Ruppe wrote: It would be part of the abi: https://dlang.org/spec/abi.html#function_calling_conventions though it references C so you might need to look that up too. That's helpful, thank you! For other sized structs and static arrays, the return value is stored through a hidden pointer passed as an argument to the function. Is there a way to access this pointer? Also, the calling convention documentation there doesn't mention anything about 64-bit targets, are 64-bit registers just not used?
Re: Where is there documentation on how to write inline asm?
On Thursday, 15 November 2018 at 20:57:59 UTC, pineapple wrote: My issue is that I can't figure out how to access a function's arguments from within inline asm or how to ensure that the correct value is returned. I haven't found a single piece of documentation about this so far! It would be part of the abi: https://dlang.org/spec/abi.html#function_calling_conventions though it references C so you might need to look that up too.
Where is there documentation on how to write inline asm?
I've managed to get a few functions working before mostly by copying whatever Phobos was doing for a similar purpose, but now that I'm trying to do something different I am really hitting a wall. My issue is that I can't figure out how to access a function's arguments from within inline asm or how to ensure that the correct value is returned. I haven't found a single piece of documentation about this so far! I am mainly concerned about doing this for naked asm functions, but any documentation on the subject would be helpful.
Re: opDispatch doesn't play nice with inheritance
On 11/15/2018 09:14 AM, Carl Sturtivant wrote: > opDispatch is special in that it allows for functions to be added to a > class or struct when undefined overtly but used elsewhere but it seems > those functions sadly are final. > > Can anything useful be done to remedy the situation? For the compiler to be able to make all opDispatch instantiations virtual, it would have to first see all calls that generate opDispatch instantiations. (Impossible in the presence of separate compilation.) Only then the compiler would know how large the vtbl of the base class should be and what member functions of the derived class are overrides of those virtual functions. I think it would be confusing as well; a function suddenly becomes virtual just because someone else made a call on the base class interface. Ali
Re: opDispatch doesn't play nice with inheritance
On Thursday, 15 November 2018 at 18:04:42 UTC, Adam D. Ruppe wrote: Right, all templates are final, including opDispatch. What I've done in the past is to forward them to a virtual function with runtime arguments instead of compile time arguments. Kinda like: void opDispatch(string name)() { callMethod(name); } /* virtual */ void callMethod(string name) { // do a reflection loop or associate array or switch or whatever to dispatch it here, reimplemented (or at least re-mixed-in) in the child classes to account for their new methods } What exactly do you need to do with it? Maybe you can do an alternative design. Well, I found an alternative design not using opDispatch, not fundamentally dissimilar to what you suggested above, thanks for that, and it's not too uneconomical in its textual organization. I was hoping to avoid doing any of my own dispatching when inheritance would do it for me.
Re: opDispatch doesn't play nice with inheritance
On Thursday, 15 November 2018 at 17:14:21 UTC, Carl Sturtivant wrote: opDispatch is special in that it allows for functions to be added to a class or struct when undefined overtly but used elsewhere but it seems those functions sadly are final. Right, all templates are final, including opDispatch. What I've done in the past is to forward them to a virtual function with runtime arguments instead of compile time arguments. Kinda like: void opDispatch(string name)() { callMethod(name); } /* virtual */ void callMethod(string name) { // do a reflection loop or associate array or switch or whatever to dispatch it here, reimplemented (or at least re-mixed-in) in the child classes to account for their new methods } What exactly do you need to do with it? Maybe you can do an alternative design.
opDispatch doesn't play nice with inheritance
//Consider this: import std.stdio; void main() { X obj = new Y; writeln( obj._f() ); } class Proxy { X x; this(X x) { this.x = x; } string _f() { return "Proxy._f called"; } } class X { auto opDispatch(string f, Args...)(Args args) { Proxy p = new Proxy(this); return mixin("p."~f~"(args)"); } } class Y : X { string _f() { return "Y._f called"; } } // Presumably the presence of obj._f()in main causes the compilation of a function _f() in the class X, yet the function _f() in Y that inherits it merely shadows it; the keyword override cannot be used for this function. opDispatch is special in that it allows for functions to be added to a class or struct when undefined overtly but used elsewhere but it seems those functions sadly are final. Can anything useful be done to remedy the situation?
Re: Writing Postgresql extension in D
On Thursday, 15 November 2018 at 13:05:59 UTC, Ranjan wrote: This is my first time on the Dlang forum. I like the language but my usecase is a bit different. I want to write Postgresql extension in D. Currently extension can be written in C or C linked languages. Has anyone done this or can point me to some code. Thanks Did you read this: https://dlang.org/spec/interfaceToC.html ? Andrea
Writing Postgresql extension in D
This is my first time on the Dlang forum. I like the language but my usecase is a bit different. I want to write Postgresql extension in D. Currently extension can be written in C or C linked languages. Has anyone done this or can point me to some code. Thanks
Re: Inherit from class based on bool value
On Thursday, 15 November 2018 at 08:46:36 UTC, Bienlein wrote: On Tuesday, 13 November 2018 at 07:10:26 UTC, Jamie wrote: I would like my class to inherit from one of two classes based on a boolean value known at compile time. Something like this: void main() { Top!(OPTION.FALSE) top = new Top!(OPTION.FALSE); } enum OPTION { FALSE = 0., TRUE = 1. } class One {} class Two {} class Top(OPTION option) : option ? One : Two {} Is this possible? I can't get it to work in the way I'm showing above. Cheers My piece of advice would be not to do this but to model all data explicitly. And I had some exposure to OOP with over 10 years developing in Smalltalk, which is a pure OO language. Actually, I don't know whether it is good that this can be done in D ... It's really no different than doing it manually and it's prettier than if it was done using a mixin, in which you'd not be able to limit it at all. D is not an OOP language and it doesn't even conform to standard OOP practices so really it doesn't matter. What doesn't make sense in one language, might make sense in another language. I feel like restrictions often limit the full potential of a language, more often than it damages it. Depending on the use-case this might make sense. It would actually be very useful for exceptions/errors in D. Something like: template ExceptionParent(Parent = Exception) { static if (flagsThatDeterminesItsDebugMode) { alias ExceptionParent = Error; } else { alias ExceptionParent = Parent; } } class MyException : ExceptionParent!() { ... } Now when debugging all exceptions will be error and when it's not debugging it'll be an exception.
Re: Inherit from class based on bool value
On Tuesday, 13 November 2018 at 07:10:26 UTC, Jamie wrote: I would like my class to inherit from one of two classes based on a boolean value known at compile time. Something like this: void main() { Top!(OPTION.FALSE) top = new Top!(OPTION.FALSE); } enum OPTION { FALSE = 0., TRUE = 1. } class One {} class Two {} class Top(OPTION option) : option ? One : Two {} Is this possible? I can't get it to work in the way I'm showing above. Cheers My piece of advice would be not to do this but to model all data explicitly. And I had some exposure to OOP with over 10 years developing in Smalltalk, which is a pure OO language. Actually, I don't know whether it is good that this can be done in D ...