Bug 6019 – Phobos imports in autogenerated .di header files break implicit linking with DLLs

Status
NEW
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
Other
OS
Windows
Creation time
2011-05-16T16:02:19Z
Last change time
2024-12-13T17:55:15Z
Keywords
dll
Assigned to
No Owner
Creator
Andrej Mitrovic
See also
https://issues.dlang.org/show_bug.cgi?id=22367, https://issues.dlang.org/show_bug.cgi?id=4071, https://issues.dlang.org/show_bug.cgi?id=9816, https://issues.dlang.org/show_bug.cgi?id=23535
Moved to GitHub: dmd#18341 →

Attachments

IDFilenameSummaryContent-TypeSize
1054dll_bug.zipDLL Bugapplication/zip1412

Comments

Comment #0 by andrej.mitrovich — 2011-05-16T16:02:19Z
Test case: http://dl.dropbox.com/u/9218759/dll_bug.zip Use the build.bat file or issue these commands: cd dll dmd -H -of..\mydll.dll -L/IMPLIB mydll.d cd.. dmd driver.d -I. dll\mydll.lib The exported D function is found by the linker, and you can find the name in the mydll.dll, mydll.lib, and driver.obj files, it has this name: _D3dll5mydll3fooFiZi However DMD also generates a mydll.obj file which references this symbol: _D3dll5mydll12__ModuleInfoZ This symbol isn't exported in the DLL and you won't find it in the import lib, and hence the linker error. Daniel Green made a comment from this thread http://www.digitalmars.com/d/archives/digitalmars/D/learn/.di_header_imports_with_DLL_symbols_fails_to_link_25571.html: "Probably unrelated, but this same issue showed up in the GDC backend. Apparently, the compiler tried to be smart about exporting ModuleInfo only for those modules that needed it. The fix was to always export it regardless." Note that you cannot just pass a .di header file directly to DMD because DMD will statically compile the mydll.foo function found in the header file, and the application won't need the DLL anymore. You also cannot prototype the foo() function directly in driver.d, because this function will be mangled together with its module name (mangled mydll.driver vs mangled driver.foo). The alternative is manually figuring out the mangling of the function name and using explicit linking via GetProcAddress & friends. --------------- One more thing: Apparently in v2.053 linking with core.dll_helper doesn't work anymore: import core.dll_helper; void main() {} Error 42: Symbol Undefined _D4core10dll_helper12__ModuleInfoZ --- errorlevel 1 Is that a known issue? Linking with core.sys.windows.dll does work though.
Comment #1 by andrej.mitrovich — 2011-05-16T18:41:33Z
Also the guide which shows how to write and use D DLLs using a similar technique and .def files exhibits the same problem (and it also imports the non-existent std.gc module): http://d-programming-language.org/dll.html
Comment #2 by andrej.mitrovich — 2011-05-16T18:47:19Z
(In reply to comment #0) > > One more thing: Apparently in v2.053 linking with core.dll_helper doesn't work > anymore: > import core.dll_helper; > void main() {} > > Error 42: Symbol Undefined _D4core10dll_helper12__ModuleInfoZ > --- errorlevel 1 > > Is that a known issue? Linking with core.sys.windows.dll does work though. Disregard that. It seems I've had this module leftover from 2.052. That should teach me not to copy/paste new releases over old ones.
Comment #3 by andrej.mitrovich — 2011-05-17T15:29:33Z
Ok, I think I have found a very simple test case: http://dl.dropbox.com/u/9218759/dll_bugs.zip The only difference between the two projects is that the one which does an import to a Phobos function will not compile. So I'm changing the title of this bug report.
Comment #4 by andrej.mitrovich — 2011-05-17T15:49:02Z
Freakin' hell. Ok so I've ran it down to blaming the header generation. Here's an example with a hand-generated .di header file versus automatically generated .di file. The hand-edited one is almost the same as the compiler generates it, except it has imports to Phobos *commented out*. http://dl.dropbox.com/u/9218759/DLL_bug_test_case.zip
Comment #5 by r.sagitario — 2011-05-17T23:53:29Z
The import in the di file tells the compiler that there are dependencies to other modules that need to be respected during module initialization. That's why they are placed into the module info. I agree it is very annoying not to be able to use the generated di files (let alone the d files). Two possible solutions: - add a switch to the compiler to only put exported symbols into the di file and leave out imports. This might make it difficult to compile this file if there are still references to symbols defined by the imports. - add a modifier to the "import" declaration that avoids adding dependencies to the module info. (IIRC this has also been discussed to break cyclic module initialization.) If used in driver.d, it might even restrict imported symbols to the symbols marked "export" in the di file. If used for the imports of the generated di-file, it might break the correct init order when used for modules built to static libraries (as druntime). BTW: I checked the generated object files: the buggy version also adds symbols _D47TypeInfo_S3std6traits15__T8DemangleTkZ8Demangle6__initZ and _D3std6traits15__T8DemangleTkZ8Demangle6__initZ. I don't know why this happens, but as these are comdats, they problably won't break anything.
Comment #6 by andrej.mitrovich — 2011-06-24T10:37:27Z
It seems another workaround for this is to create a dummy symbol in the module that imports a header file, e.g.: extern(C) int D3dll5mydll12__ModuleInfoZ; // implicitly adds _ before the name This fixes linker errors. However it has to be put in the module that imports "dll.mydll", and not inside dll.mydll module itself as that creates some kind of symbol clashes.
Comment #7 by andrej.mitrovich — 2011-12-18T10:43:50Z
Created attachment 1054 DLL Bug
Comment #8 by andrej.mitrovich — 2011-12-18T10:44:25Z
(In reply to comment #7) > Created an attachment (id=1054) [details] > DLL Bug The other samples bit-rotted, newest one is in the attachment.
Comment #9 by code — 2013-10-02T04:42:10Z
*** Issue 9220 has been marked as a duplicate of this issue. ***
Comment #10 by code — 2013-10-02T05:08:42Z
Most declarations don't require linkage. The ones that do are module ctors/dtors (__ModuleInfoZ), classes (vtbl and classinfo) and anything that's non-zero initialized (__initZ), i.e. structs with non-zero initialized fields, enums with non-zero first member, char and maybe floats. BTW the same issue is present in deimos where you also want headers that don't require linkage. Maybe we can come up with a good idea how to solve this. How about this? Using weak undefined symbols to link against the imported ModuleInfo would result in null pointers during runtime.
Comment #11 by code — 2013-10-02T08:51:30Z
(In reply to comment #10) > How about this? Using weak undefined symbols to link against the imported > ModuleInfo would result in null pointers during runtime. That could cause some issues with the weird multilibs. Not sure currently if every archive member references it's module's ModuleInfo.
Comment #12 by alphaglosined — 2022-11-25T16:31:27Z
I'm removing the bootcamp keyword from this bug. Setting a symbol as export is not enough to get this working. DllImport while in theory implemented in dmd as of 2.102.0 does not do any patching at runtime required to dereference the pointer. I went into attempting to solve this in my post here: https://forum.dlang.org/post/[email protected]
Comment #13 by bugzilla — 2023-06-04T07:10:24Z
Comment #14 by robert.schadek — 2024-12-13T17:55:15Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/18341 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB