www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Undefined (Win32) Externals

reply Loopback <elliott.darfink gmail.com> writes:
Hi!

Let me begin by saying, that I haven't used Usenet newsgroup at all, so 
please excuse me for any errors or misunderstandings of the guidelines.

I recently begun programming a win32 application though I instantly got 
stuck with a problem. As you might know, win32 applications require that 
you define the WindowProc function for processing window messages.

I've used a object-oriented approach for this, and that requires that 
you declare the WindowProc function as static, and bind your own class 
(hWnd) to GWL_USERDATA, to be able to call your own, class defined, 
message handler (WindowProc). To do this, you have to access the two 
functions GetWindowLong and SetWindowLong.

For some reason, these functions do not exist in the windows module 
(std.c.windows.windows), neither does the GWL_USERDATA constant.

To solve this I've used this alternative code:

extern (Windows)
{
	int GWL_USERDATA;
	LONG SetWindowLong(HWND, int, LONG);
	LONG GetWindowLong(HWND, int);
}

When I then try to compile this application, the GWL_USERDATA constant 
compiles without any errors, but the Get-/SetWindowLong produces linker 
errors.

To solve the linker errors, I checked which library they were contained 
in, on MSDN it said User32.lib. Therefore I linked to this library - 
without any success.

So to summarize, how do I solve these linker errors:

Error 42: Symbol Undefined _SetWindowLong 12
Error 42: Symbol Undefined _GetWindowLong 8

Sorry for such a long message!
Any help is greatly appreciated!
Jun 12 2011
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Use the WindowsAPI bindings from here:
http://dsource.org/projects/bindings/wiki/WindowsApi

Pass -version=Unicode and various other version specifiers based on
what you need. Otherwise, a typical Win32 example looks like this:

http://codepad.org/cP2XrrHS

For what it's worth, I will (hopefully) soon publish D translated
examples from the Programming Windows book, by Charles Petzold. It
contains about 145 examples (a few dozen were left out in the D
translation because they covered 8-bit displays which don't exist
anymore).

But I have yet to receive an e-mail back from Petzold regarding the
copyright/licensing of his code. Until I get back from him, I can't
publish the code.
Jun 12 2011
parent reply Loopback <elliott.darfink gmail.com> writes:
On 2011-06-13 00:50, Andrej Mitrovic wrote:
 Use the WindowsAPI bindings from here:
 http://dsource.org/projects/bindings/wiki/WindowsApi

 Pass -version=Unicode and various other version specifiers based on
 what you need. Otherwise, a typical Win32 example looks like this:

 http://codepad.org/cP2XrrHS

 For what it's worth, I will (hopefully) soon publish D translated
 examples from the Programming Windows book, by Charles Petzold. It
 contains about 145 examples (a few dozen were left out in the D
 translation because they covered 8-bit displays which don't exist
 anymore).

 But I have yet to receive an e-mail back from Petzold regarding the
 copyright/licensing of his code. Until I get back from him, I can't
 publish the code.
Great, thanks for the link! Though I do have to ask, are these bindings any mature? Most of the files in the SVN repository are about 4 years old.
Jun 12 2011
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Well most API functions stay the same for a long time on Windows.
Examples compiled in 1998 for Windows 98 will compile in 2011 for
Windows 7, and they will both run fine. At least the simple ones will.
The bindings /might/ be missing some new vista/win7 function
prototypes but I'm not sure if that's true or not. And if you use
vista/win7 features exclusively, you can say goodbye to compatibility
with pre-vista systems (if you care about that).

I'm not sure why your example is not compiling for you, it does for me:

import std.c.windows.windows;

extern (Windows)
{
       int GWL_USERDATA;
       LONG SetWindowLong(HWND, int, LONG);
       LONG GetWindowLong(HWND, int);
}

void main()
{
}

But try replacing the prototypes with this (notice the A at the end):
       LONG SetWindowLongA(HWND, int, LONG);
       LONG GetWindowLongA(HWND, int);

Which DMD version are you running?
Jun 12 2011
parent reply Loopback <elliott.darfink gmail.com> writes:
On 2011-06-13 01:53, Andrej Mitrovic wrote:
 Well most API functions stay the same for a long time on Windows.
 Examples compiled in 1998 for Windows 98 will compile in 2011 for
 Windows 7, and they will both run fine. At least the simple ones will.
 The bindings /might/ be missing some new vista/win7 function
 prototypes but I'm not sure if that's true or not. And if you use
 vista/win7 features exclusively, you can say goodbye to compatibility
 with pre-vista systems (if you care about that).

 I'm not sure why your example is not compiling for you, it does for me:

 import std.c.windows.windows;

 extern (Windows)
 {
         int GWL_USERDATA;
         LONG SetWindowLong(HWND, int, LONG);
         LONG GetWindowLong(HWND, int);
 }

 void main()
 {
 }

 But try replacing the prototypes with this (notice the A at the end):
         LONG SetWindowLongA(HWND, int, LONG);
         LONG GetWindowLongA(HWND, int);

 Which DMD version are you running?
Replacing them with their ASCII variants worked flawlessly! Though GWL_USERDATA is apparently undefined (0). To solve this I had to declare the variable explicitly: const int GWL_USERDATA = -21; About the WindowsAPI binding, is it fully functional for D2, since it seems to have been inactive for so long? Even though I've solved this error (Set-/GetWindowLong) I've got stuck with another error (this might be off topic, perhaps a new thread?) related to DirectX. At the moment I'm using the DDirectX9 binding (at dsource.org). So far it's been working perfectly fine, everything compiles and no linker errors, but I do have problems with creating the Direct3D9 Device. The reason I am asking this here (and not in a forum related to DirectX) is because there are no debug outputs, even with the DirectX debug DLLs, I guess this is related to the D debugger or the wrapper? To get to the problem, in my code, I set up a Win32 Window like this: // Window Properties WNDCLASSA wnd; // Setup The Properties wnd.style = CS_HREDRAW | CS_VREDRAW; wnd.lpfnWndProc = &WindowProc; wnd.hInstance = hInstance; wnd.lpszClassName = "CWindow"; // Register Class RegisterClassA(&wnd); // Create Window m_hWnd = CreateWindowA("CWindow", "Win32&DirectX Test", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, null, null, hInstance, null); // Used for static WindowProc SetWindowLongA(m_hWnd, GWL_USERDATA, cast(LONG)(cast(void*) this)); // Show & Update The Window ShowWindow(m_hWnd, SW_SHOW); UpdateWindow(m_hWnd); After this, I set up the direct3d environment with this code: // Create Direct3D Interface m_d3d = Direct3DCreate9(D3D_SDK_VERSION); // <--- This is successful // Present Parameters D3DPRESENT_PARAMETERS d3dpp = {0}; // Setup the options d3dpp.Windowed = true; d3dpp.SwapEffect = D3DSWAPEFFECT.D3DSWAPEFFECT_DISCARD; d3dpp.hDeviceWindow = m_hWnd; // Create Direct3D Device HRESULT hr = m_d3d.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE.D3DDEVTYPE_HAL, m_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &m_d3dDevice); if(FAILED(hr)) MessageBoxA(null, "Failurreeeee", "Majs", MB_ICONERROR); The HRESULT from CreateDevice always returns the following: HRESULT: 0x8876086c (2289436780) Name: D3DERR_INVALIDCALL Description: Invalid call Severity code: Failed Facility Code: FACILITY_D3D (2166) Error Code: 0x086c (2156) I've googled this a lot with no avail, and since my code is so small, I'm afraid it's related to D or the DirectX Wrapper. I've tried to play a bit with the d3dpresent parameters without success... Once again, I'm sorry if it's inconvenient to post this here, although this seems like the most appropriate place. (if worth noticing, I'm using DMD Version 2.052 and the wrapper is D1)
Jun 12 2011
parent Loopback <elliott.darfink gmail.com> writes:
On 2011-06-13 03:54, Loopback wrote:
 On 2011-06-13 01:53, Andrej Mitrovic wrote:
 Well most API functions stay the same for a long time on Windows.
 Examples compiled in 1998 for Windows 98 will compile in 2011 for
 Windows 7, and they will both run fine. At least the simple ones will.
 The bindings /might/ be missing some new vista/win7 function
 prototypes but I'm not sure if that's true or not. And if you use
 vista/win7 features exclusively, you can say goodbye to compatibility
 with pre-vista systems (if you care about that).

 I'm not sure why your example is not compiling for you, it does for me:

 import std.c.windows.windows;

 extern (Windows)
 {
 int GWL_USERDATA;
 LONG SetWindowLong(HWND, int, LONG);
 LONG GetWindowLong(HWND, int);
 }

 void main()
 {
 }

 But try replacing the prototypes with this (notice the A at the end):
 LONG SetWindowLongA(HWND, int, LONG);
 LONG GetWindowLongA(HWND, int);

 Which DMD version are you running?
Replacing them with their ASCII variants worked flawlessly! Though GWL_USERDATA is apparently undefined (0). To solve this I had to declare the variable explicitly: const int GWL_USERDATA = -21; About the WindowsAPI binding, is it fully functional for D2, since it seems to have been inactive for so long? Even though I've solved this error (Set-/GetWindowLong) I've got stuck with another error (this might be off topic, perhaps a new thread?) related to DirectX. At the moment I'm using the DDirectX9 binding (at dsource.org). So far it's been working perfectly fine, everything compiles and no linker errors, but I do have problems with creating the Direct3D9 Device. The reason I am asking this here (and not in a forum related to DirectX) is because there are no debug outputs, even with the DirectX debug DLLs, I guess this is related to the D debugger or the wrapper? To get to the problem, in my code, I set up a Win32 Window like this: // Window Properties WNDCLASSA wnd; // Setup The Properties wnd.style = CS_HREDRAW | CS_VREDRAW; wnd.lpfnWndProc = &WindowProc; wnd.hInstance = hInstance; wnd.lpszClassName = "CWindow"; // Register Class RegisterClassA(&wnd); // Create Window m_hWnd = CreateWindowA("CWindow", "Win32&DirectX Test", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, null, null, hInstance, null); // Used for static WindowProc SetWindowLongA(m_hWnd, GWL_USERDATA, cast(LONG)(cast(void*) this)); // Show & Update The Window ShowWindow(m_hWnd, SW_SHOW); UpdateWindow(m_hWnd); After this, I set up the direct3d environment with this code: // Create Direct3D Interface m_d3d = Direct3DCreate9(D3D_SDK_VERSION); // <--- This is successful // Present Parameters D3DPRESENT_PARAMETERS d3dpp = {0}; // Setup the options d3dpp.Windowed = true; d3dpp.SwapEffect = D3DSWAPEFFECT.D3DSWAPEFFECT_DISCARD; d3dpp.hDeviceWindow = m_hWnd; // Create Direct3D Device HRESULT hr = m_d3d.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE.D3DDEVTYPE_HAL, m_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &m_d3dDevice); if(FAILED(hr)) MessageBoxA(null, "Failurreeeee", "Majs", MB_ICONERROR); The HRESULT from CreateDevice always returns the following: HRESULT: 0x8876086c (2289436780) Name: D3DERR_INVALIDCALL Description: Invalid call Severity code: Failed Facility Code: FACILITY_D3D (2166) Error Code: 0x086c (2156) I've googled this a lot with no avail, and since my code is so small, I'm afraid it's related to D or the DirectX Wrapper. I've tried to play a bit with the d3dpresent parameters without success... Once again, I'm sorry if it's inconvenient to post this here, although this seems like the most appropriate place. (if worth noticing, I'm using DMD Version 2.052 and the wrapper is D1)
I've found a solution to the problem, though not the reason. Would be great if someone could explain. However, using only this code: d3dpp.Windowed = true; d3dpp.SwapEffect = D3DSWAPEFFECT.D3DSWAPEFFECT_DISCARD; d3dpp.hDeviceWindow = m_hWnd; The CreateDevice functions throws an D3DERR_INVALIDCALL error. To avoid this, you have to specify every single parameter individually, etc. This code worked flawlessly for me (Windowed Mode): D3DPRESENT_PARAMETERS d3dpp = {0, 0, D3DFMT_UNKNOWN, 1, D3DMULTISAMPLE_NONE, 0, D3DSWAPEFFECT_DISCARD, m_hWnd, TRUE, FALSE, 0, 0, 0, 0 }; No what I am wondering is this; how come this works but not the other code snippet? These are more or less equal except that I don't use the initializer construct for one of the snippets.
Jun 14 2011
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-12 15:39, Loopback wrote:
 Hi!
 
 Let me begin by saying, that I haven't used Usenet newsgroup at all, so
 please excuse me for any errors or misunderstandings of the guidelines.
 
 I recently begun programming a win32 application though I instantly got
 stuck with a problem. As you might know, win32 applications require that
 you define the WindowProc function for processing window messages.
 
 I've used a object-oriented approach for this, and that requires that
 you declare the WindowProc function as static, and bind your own class
 (hWnd) to GWL_USERDATA, to be able to call your own, class defined,
 message handler (WindowProc). To do this, you have to access the two
 functions GetWindowLong and SetWindowLong.
 
 For some reason, these functions do not exist in the windows module
 (std.c.windows.windows), neither does the GWL_USERDATA constant.
 
 To solve this I've used this alternative code:
 
 extern (Windows)
 {
 	int GWL_USERDATA;
 	LONG SetWindowLong(HWND, int, LONG);
 	LONG GetWindowLong(HWND, int);
 }
 
 When I then try to compile this application, the GWL_USERDATA constant
 compiles without any errors, but the Get-/SetWindowLong produces linker
 errors.
 
 To solve the linker errors, I checked which library they were contained
 in, on MSDN it said User32.lib. Therefore I linked to this library -
 without any success.
 
 So to summarize, how do I solve these linker errors:
 
 Error 42: Symbol Undefined _SetWindowLong 12
 Error 42: Symbol Undefined _GetWindowLong 8
 
 Sorry for such a long message!
 Any help is greatly appreciated!
I believe that you need extern(C) around those functions. They're C functions, not D functions. - Jonathan M Davis
Jun 12 2011
next sibling parent Loopback <elliott.darfink gmail.com> writes:
On 2011-06-13 01:16, Jonathan M Davis wrote:
 On 2011-06-12 15:39, Loopback wrote:
 Hi!

 Let me begin by saying, that I haven't used Usenet newsgroup at all, so
 please excuse me for any errors or misunderstandings of the guidelines.

 I recently begun programming a win32 application though I instantly got
 stuck with a problem. As you might know, win32 applications require that
 you define the WindowProc function for processing window messages.

 I've used a object-oriented approach for this, and that requires that
 you declare the WindowProc function as static, and bind your own class
 (hWnd) to GWL_USERDATA, to be able to call your own, class defined,
 message handler (WindowProc). To do this, you have to access the two
 functions GetWindowLong and SetWindowLong.

 For some reason, these functions do not exist in the windows module
 (std.c.windows.windows), neither does the GWL_USERDATA constant.

 To solve this I've used this alternative code:

 extern (Windows)
 {
 	int GWL_USERDATA;
 	LONG SetWindowLong(HWND, int, LONG);
 	LONG GetWindowLong(HWND, int);
 }

 When I then try to compile this application, the GWL_USERDATA constant
 compiles without any errors, but the Get-/SetWindowLong produces linker
 errors.

 To solve the linker errors, I checked which library they were contained
 in, on MSDN it said User32.lib. Therefore I linked to this library -
 without any success.

 So to summarize, how do I solve these linker errors:

 Error 42: Symbol Undefined _SetWindowLong 12
 Error 42: Symbol Undefined _GetWindowLong 8

 Sorry for such a long message!
 Any help is greatly appreciated!
I believe that you need extern(C) around those functions. They're C functions, not D functions. - Jonathan M Davis
Thanks for you reply though linker errors (Symbol Undefined) are still generated even though I've specified the functions as external C.
Jun 12 2011
prev sibling parent KennyTM~ <kennytm gmail.com> writes:
On Jun 13, 11 07:16, Jonathan M Davis wrote:
 On 2011-06-12 15:39, Loopback wrote:
 Hi!

 Let me begin by saying, that I haven't used Usenet newsgroup at all, so
 please excuse me for any errors or misunderstandings of the guidelines.

 I recently begun programming a win32 application though I instantly got
 stuck with a problem. As you might know, win32 applications require that
 you define the WindowProc function for processing window messages.

 I've used a object-oriented approach for this, and that requires that
 you declare the WindowProc function as static, and bind your own class
 (hWnd) to GWL_USERDATA, to be able to call your own, class defined,
 message handler (WindowProc). To do this, you have to access the two
 functions GetWindowLong and SetWindowLong.

 For some reason, these functions do not exist in the windows module
 (std.c.windows.windows), neither does the GWL_USERDATA constant.

 To solve this I've used this alternative code:

 extern (Windows)
 {
 	int GWL_USERDATA;
 	LONG SetWindowLong(HWND, int, LONG);
 	LONG GetWindowLong(HWND, int);
 }

 When I then try to compile this application, the GWL_USERDATA constant
 compiles without any errors, but the Get-/SetWindowLong produces linker
 errors.

 To solve the linker errors, I checked which library they were contained
 in, on MSDN it said User32.lib. Therefore I linked to this library -
 without any success.

 So to summarize, how do I solve these linker errors:

 Error 42: Symbol Undefined _SetWindowLong 12
 Error 42: Symbol Undefined _GetWindowLong 8

 Sorry for such a long message!
 Any help is greatly appreciated!
I believe that you need extern(C) around those functions. They're C functions, not D functions. - Jonathan M Davis
extern(Windows) is correct since they have WINAPI calling convention. The problem is their actual names are Get/SetWindowLongW/A...
Jun 12 2011