Re: How to call a function from a dll created with d ?
On 7/1/22 12:11, Vinod KC wrote: The following function is dimedll.testFunc: > ```d > module dimedll; // ... > export void testFunc() { > writeln("This is from dll"); > } > ``` We suspect the name of the file that defines main() is dime.d. > extern void testFunc(); That symbol belongs to this module, which is implied to be 'module dime'. > testFunc(); That's a call to dime.testFunc, which does not exist. With the provided information alone, the following is what I would do: 1) This dll must have a .di file, which should contain the following: // dimedll.di void testFunc(); (.di files can be generated by dmd with its -H command line switch.) 2) Provide dimedll.di as your library's interface file (a la "header file"). 3) The users of this dll should import that .di file (declaring the functions themselves won't work): import dimedll; void main() { // ... } Ali
Re: How to call a function from a dll created with d ?
On Saturday, 2 July 2022 at 00:23:20 UTC, Ruby The Roobster wrote: The solution is to remove the extern declaration. That does it for me, and it prints the expected output. No need for a .def file, unless you are using optlink as your linker (which, as a matter of principle, you should use lld or ld instead.) Thank you for the reply. Let me try that.
Re: How to call a function from a dll created with d ?
The solution is to remove the extern declaration. That does it for me, and it prints the expected output. No need for a .def file, unless you are using optlink as your linker (which, as a matter of principle, you should use lld or ld instead.)
Re: How to call a function from a dll created with d ?
On Friday, 1 July 2022 at 22:38:17 UTC, Adam D Ruppe wrote: On Friday, 1 July 2022 at 22:32:24 UTC, Vinod K Chandran wrote: So using a `def` file is a must I think. no it is not. you just need to mark things export and make sure names match (including module name) Thanks for the reply. These are my questions. 1. `mixin` statement in dll file - Do I need to export it ? 2. There is only one function and that is marked with `export`. 3. Name of the module which I wrote the dll code is `dimedll`. So my dll file's name is `dimedll.dll`. And my lib file's name is `dimedll.lib`. No change in names. 4. Name of my exported function is `testFunc`. And the same name is used in `extern` keyword and the calling site. So where do I check again ?
Re: How to call a function from a dll created with d ?
On Friday, 1 July 2022 at 22:32:24 UTC, Vinod K Chandran wrote: So using a `def` file is a must I think. no it is not. you just need to mark things export and make sure names match (including module name)
Re: How to call a function from a dll created with d ?
On Friday, 1 July 2022 at 22:22:42 UTC, mw wrote: Try follow instructions here: https://wiki.dlang.org/Win32_DLLs_in_D Thanks. So using a `def` file is a must I think. At first, I thought I can skip that.
Re: How to call a function from a dll created with d ?
On Friday, 1 July 2022 at 21:15:50 UTC, Vinod K Chandran wrote: On Friday, 1 July 2022 at 21:02:20 UTC, mw wrote: I think the problem is the linker looking for dime.testFunc, while your lib function is dimedll.testFunc Thanks for the reply. What about this `mixin SimpleDllMain;` I suspect this. Try follow instructions here: https://wiki.dlang.org/Win32_DLLs_in_D
Re: How to call a function from a dll created with d ?
On Friday, 1 July 2022 at 21:02:20 UTC, mw wrote: I think the problem is the linker looking for dime.testFunc, while your lib function is dimedll.testFunc Thanks for the reply. What about this `mixin SimpleDllMain;` I suspect this.
Re: How to call a function from a dll created with d ?
On Friday, 1 July 2022 at 19:11:16 UTC, Vinod KC wrote: Hi all, I have created a dll file with this code. ```d module dimedll; export void testFunc() { writeln("This is from dll"); } ``` void main() { log("Lets build our own ime"); testFunc(); } ``` ``` dime.obj : error LNK2019: unresolved external symbol __D4dime8testFuncFZv referenced in I think the problem is the linker looking for dime.testFunc, while your lib function is dimedll.testFunc
Re: How to call a function from a dll created with d ?
On Friday, 1 July 2022 at 20:08:45 UTC, ryuukk_ wrote: I think it is `extern(D) void testFunc();`? Thanks for the reply. But the result is same linker error.
Re: How to call a function from a dll created with d ?
I think it is `extern(D) void testFunc();`?
How to call a function from a dll created with d ?
Hi all, I have created a dll file with this code. ```d module dimedll; import core.sys.windows.windows; import core.sys.windows.dll; // I don't what is this for. import std.stdio; mixin SimpleDllMain; export void testFunc() { writeln("This is from dll"); } ``` So now I have a dll fie named `dimedll.dll` and a lib file named `dimedll.lib`. Now, I have created a d source file called `dime.d` and wrote this code. ```d import std.stdio; import core.sys.windows.windows; import std.stdio : log = writeln; pragma(lib, "dimedll.lib"); extern void testFunc(); void main() { log("Lets build our own ime"); testFunc(); } ``` Everything seems to be okay. So I called dmd with this command. `dmd -i -run dime.d` But I got this error message. ``` dime.obj : error LNK2019: unresolved external symbol __D4dime8testFuncFZv referenced in function __Dmain dime.exe : fatal error LNK1120: 1 unresolved externals Error: linker exited with status 1120``` How to fix this ?
Re: How to check if something can be null
On Friday, 1 July 2022 at 15:35:00 UTC, Adam D Ruppe wrote: On Friday, 1 July 2022 at 13:48:25 UTC, Antonio wrote: I has been using this pattern each time something needs special treatment when it can be null: i'd prolly check `static if(is(typeof(null) : T))` which means if the null literal implicitly converts to type T. Perfect!!! Thanks Adam. there's also the bludgeon __traits(compiles, v is null) too lol love it X-) !!! may be this is the Swiss knife I was waiting for...
Re: How to check if something can be null
On Friday, 1 July 2022 at 13:48:25 UTC, Antonio wrote: I has been using this pattern each time something needs special treatment when it can be null: i'd prolly check `static if(is(typeof(null) : T))` which means if the null literal implicitly converts to type T. there's also the bludgeon __traits(compiles, v is null) too lol
Re: How to check if something can be null
On Friday, 1 July 2022 at 13:53:28 UTC, Antonio wrote: On Friday, 1 July 2022 at 13:48:25 UTC, Antonio wrote: -Why? I realized Json is an struct (not an object)... and I supose, it is managing null asignation manually (as a way to build Json(null)). -Whats the correct whay to test if something can be null? That's my question :-p Something like this does the job: ```d enum canBeNull(T) = is(typeof({T t; t = null;})); static assert(canBeNull!(Object)); static assert(!canBeNull!(int)); ``` and that should handle opAssign and opCmp overloads.
Re: dlang bug - accessing module variable from method segfaults only when using module reference directly
On Friday, 1 July 2022 at 13:44:20 UTC, Chris Katko wrote: It appears module access to a class is broken until the constructor finishes. No, it has nothing to do with the module. It's the reference itself. Until the constructor returns, the reference through which you're constructing the instance is null. It doesn't matter if it's at module scope, function scope, or wherever. If the constructor fails to complete (segfault, thrown exception, assertion failure, etc.), then the reference remains null. The reference is not the *instance*. It's a pointer to the instance. The instance is valid when the constructor is called, because the `this` reference has to be valid. Think of it in terms of a normal function call: ```D T newT() { T t = allocT(); t.construct(t); return t; } T g = newT(); ``` If `t.construct` throws or crashes, then `return t` is never executed, and `g` is never initialized.
Re: How to check if something can be null
On Friday, 1 July 2022 at 13:48:25 UTC, Antonio wrote: -Why? I realized Json is an struct (not an object)... and I supose, it is managing null asignation manually (as a way to build Json(null)). -Whats the correct whay to test if something can be null? That's my question :-p
How to check if something can be null
I has been using this pattern each time something needs special treatment when it can be null: ```d void doSomething(T)(T v) { import std.traits: isAssignable; static if( isAssignable!(T, typeof(null))) { if(v is null) writeln("This is null"); else writeln("This is not null"); } else { writeln("This can't be null"); } } ``` and then ```d void main(){ // output: This is null doSomething!string(null); // output: This is not null doSomething("Hello"); // output: This can't be null soSomething!int(1); } ``` Problem appears with `vibe-d` `Json`. ```d void main(){ doSomething!Json(null); } ``` Compiler outputs `Error: incompatible types for `(v) is (null)`: `Json` and `typeof(null)` -Why? -Whats the correct whay to test if something can be null?
Re: dlang bug - accessing module variable from method segfaults only when using module reference directly
On Friday, 1 July 2022 at 13:28:26 UTC, Chris Katko wrote: ...wait, does "world" not 'exist' until after the constructor finishes? Is that's what's going on? But then why does it 'exist' when I send it directly? Is it only "registered" with the module once this() finishes or something like that? Yep, that's it. moving all code in world.this() to world.initialize() and immediately calling initialize, works fine. D g.world = new g.world_t; // code would crash here g.world.initialize(); // doesn't crash if moved here class world { this(){} void initialize(){/*...*/} } class elf : unit { this(pair _pos, atlasHandler atlas/*not used*/) { super(0, _pos, pair(0, 0), g.dude_bmp); anim = new animation(1, elf_coords, g.world.atlas); //not crashing now } } It appears module access to a class is broken until the constructor finishes.
Re: dlang bug - accessing module variable from method segfaults only when using module reference directly
On Friday, 1 July 2022 at 13:12:05 UTC, Adam D Ruppe wrote: On Friday, 1 July 2022 at 12:57:01 UTC, Chris Katko wrote: Cannot access memory at address 0x10 Looks like an ordinary null pointer. How did you create the variable? D bool initialize() //called from main { g.world = new world_t; } class atlasHandler{} class animation { this(int _numFrames, ipair[] coordinates, atlasHandler atlas) { } } class world_t { atlasHandler atlas; this() { viewTest(); atlas = new atlasHandler(); units ~= new elf(pair(200, 200), atlas); //crashes } logic() { // doesn't crash units ~= new elf(pair(200, 200), atlas); } } class elf : unit { this(pair _pos, atlasHandler atlas) { super(0, _pos, pair(0, 0), g.dude_bmp); // anim = new animation(1, elf_coords, atlas); //doesn't crash anim = new animation(1, elf_coords, g.world.atlas); //CRASH here isTreeWalker = true; } } also important. it seems to only occur in the constructor. If I create an elf after the world constructor, it's fine. ...wait, does "world" not 'exist' until after the constructor finishes? Is that's what's going on? But then why does it 'exist' when I send it directly? Is it only "registered" with the module once this() finishes or something like that?
Re: dlang bug - accessing module variable from method segfaults only when using module reference directly
On Friday, 1 July 2022 at 13:20:15 UTC, Mike Parker wrote: r. And that also looks like the source of your original segfault. You've got a circular reference going on in the constructors. In other words, you're constructing a global world instance, which in turn constructs an elf instance, which in turn accesses the global world reference whose constructor hasn't yet completed, so the global world reference is still null. Here's what it looks like in code: ```d import std.stdio : writeln; class Foo { Bar b; this() { b = new Bar; } void sayMyName() { writeln("I am Foo."); } } class Bar { this() { f.sayMyName(); } } Foo f; void main() { f = new Foo; } ```
Re: dlang bug - accessing module variable from method segfaults only when using module reference directly
On Friday, 1 July 2022 at 13:01:30 UTC, Chris Katko wrote: Forgot the last line. That's important because world MUST exist by time elf is called... because world... created and called elf. So it's not a memory issue, but some sort of linkage issue. world is null because the constructor didn't complete. The segfault happens inside its constructor. And that also looks like the source of your original segfault. You've got a circular reference going on in the constructors. In other words, you're constructing a global world instance, which in turn constructs an elf instance, which in turn accesses the global world reference whose constructor hasn't yet completed, so the global world reference is still null. If the objects world is constructing absolutely need to access it, then you could: 1. Initialize world with a do-nothing destructor, then call a `setup` method on it to do what its constructor currently is doing; 2. Pass `this` along to all the constructors that need it from inside the world constructor.
Re: dlang bug - accessing module variable from method segfaults only when using module reference directly
On Friday, 1 July 2022 at 12:57:01 UTC, Chris Katko wrote: Cannot access memory at address 0x10 Looks like an ordinary null pointer. How did you create the variable?
Re: dlang bug - accessing module variable from method segfaults only when using module reference directly
Forgot the last line. That's important because world MUST exist by time elf is called... because world... created and called elf. So it's not a memory issue, but some sort of linkage issue.
Re: dlang bug - accessing module variable from method segfaults only when using module reference directly
To add, I cannot even access g.world from inside elf's constructor. ... which is the function that called it. D Thread 1 "main" received signal SIGSEGV, Segmentation fault. objects.elf.this(g.pair, objects.atlasHandler) (this=, atlas=, _pos=...) at ./src/objects.d:320 (gdb) bt #0 objects.elf.this(g.pair, objects.atlasHandler) (this=, atlas=, _pos=...) at ./src/objects.d:320 #1 worldmod.world_t.this() (this=) at ./src/worldmod.d:60 #2 main.initialize() () at ./src/main.d:110 #3 main.main(immutable(char)[][]).__lambda6() (__capture=) at ./src/main.d:462 #4 allegro5.system.al_run_allegro(scope int() delegate).main_runner(int, char**) () #5 allegro5.system.al_run_allegro(scope int() delegate) () #6 D main (args=...) at ./src/main.d:461 (gdb) x g.world 0x0:Cannot access memory at address 0x0
dlang bug - accessing module variable from method segfaults only when using module reference directly
dmd (but I think LDC also is affected) this bug has bit me multiple times now, to the point I can recognize it. Accessing module variables, from inside a method, causes a segfault. Even if the variable should be available by then through the call order. Proving that its a bug, you can directly send the exact same variable through an argument, and it works fine. (not sure if this code will do it, last time I tried to replicate it with solely this kind of code, the bug disappeared.) D /// module g.d class world { atlasHandler atlas; void do() { atlas = new AtlasHanlder(); elf e = new elf(atlas); } } /// module 'objects.d' class atlasHandler{} class elf { this(atlasHandler atlas) { assert(atlas !is null); //works fine assert(g.world.atlas !is null); //crashes writefln("atlas [%p] vs g.world.atlas [%s]", atlas, g.world.atlas); // crashes trying to read g.world.atlas } } gdb output (not the exact same module names but you get the point): Thread 1 "main" received signal SIGSEGV, Segmentation fault. (gdb) p atlas $1 = (objects.atlasHandler *) (gdb) p g.world $2 = (worldmod.world_t *) (gdb) p g.world.atlas Cannot access memory at address 0x10 (gdb) p this $3 = (objects.elf *) (gdb) x atlas 0x7fffec1cf380: 0x55826580 (gdb) x g.world.atlas Cannot access memory at address 0x10 It appears that whatever value its sending, is in a protected memory segment and automatically segfaulting even upon reading. Worst case I can public my repo and you can see it for yourself.