www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - BetterC Name Mangling Linker Errors

reply MyNameHere <MyNameHere email.com> writes:
I have included the source to a simple 64-bit Windows program.
It compiles and runs fine with ```dmd -m64 
-L="/Subsystem:Windows" -L="/Entry:Main" Main.d```. But compiling 
with ```-betterC``` using the following throws up a linker error, 
```dmd -m64 -betterC -L="/Subsystem:Windows" -L="/Entry:Main" 
Main.d```:

```Main.obj : error LNK2019: unresolved external symbol 
_D4core3sys7windows7winuser11WNDCLASSEXA6__initZ referenced in 
function Main```

And I'm not sure why.

```d
import core.sys.windows.winuser;
import core.sys.windows.winbase;

pragma(lib, "User32.lib");
pragma(lib, "Kernel32.lib");

extern(Windows)
void Main(void* Instance)
{
     WNDCLASSEXA WindowClass;
     with (WindowClass)
     {
         cbSize        = WindowClass.sizeof;
         lpfnWndProc   = &WindowProc;
         hInstance     = Instance;
         hCursor       = LoadCursor(null, IDC_ARROW);
         lpszClassName = "Window";
     }
     RegisterClassExA(&WindowClass);
     void *WindowHandle = CreateWindowExA(0,
                                          "Window",
                                          "Window",
                                          WS_OVERLAPPEDWINDOW,
                                          CW_USEDEFAULT,
                                          CW_USEDEFAULT,
                                          CW_USEDEFAULT,
                                          CW_USEDEFAULT,
                                          null,
                                          null,
                                          Instance,
                                          null);
     ShowWindow(WindowHandle, SW_MAXIMIZE);

     MSG Message;
     while (GetMessage(&Message, null, 0, 0))
     {
         TranslateMessage(&Message);
         DispatchMessage(&Message);
     }
}

extern(Windows)
long WindowProc(void* WindowHandle, uint Message, ulong WParam, 
long LParam) nothrow  system
{
     if (Message == WM_DESTROY) ExitProcess(0);

     return DefWindowProcA(WindowHandle, Message, WParam, LParam);
}
```
Jul 27 2022
parent reply Dennis <dkorpel gmail.com> writes:
On Wednesday, 27 July 2022 at 12:26:59 UTC, MyNameHere wrote:
 ```d
 void Main(void* Instance)
 {
     WNDCLASSEXA WindowClass;
 ```
This is equivalent to `WNDCLASSEXA WindowClass = WNDCLASSEXA.init;` If the struct's fields all initialize to 0, the compiler would simply set the variable's bytes to 0, but the definition in druntime gives fields with non-zero default value: ```D struct WNDCLASSEXA { UINT cbSize = WNDCLASSEXA.sizeof; // <-- non zero init UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCSTR lpszMenuName; LPCSTR lpszClassName; HICON hIconSm; } ``` Because of this, the compiler defines an 'init symbol' in druntime that gets copied into your variable to initialize it. Because druntime isn't linked when using BetterC, the linker fails to find the init symbol. I think removing the default initialization will fix it: ```D WNDCLASSEXA WindowClass = void; ```
Jul 27 2022
parent MyNameHere <MyNameHere email.com> writes:
Thank you, that seems to have been the source of the error.
Jul 27 2022