Handmade Hero»Forums»Code
Timothy McCarthy
52 posts
DirectInput variable location
I'm having a problem getting a variable out of the DirectInput library.

This is for a 32 bit build (but that shouldn't be affecting this.) The goal is to be able to load the dinput8.dll on demand.

The dinput.dll is loaded on demand via LoadLibrary

1
HINSTANCE hinst = ::LoadLibrary("dinput8.dll");


The pointer to the DirectInput8Create function is obtained via ::GetProcAddress

1
FARPROC InputCreate = ::GetProcAddress("DirectInput8Create");


When I get to the point of creating a joystick device I want to use the predefined library variable "c_dfDIJoystick2." I should be able to get a pointer to it with GetProcAddress

1
const DIDATAFORMAT * pc_dfDIJoystick2 = (const DIDATAFORMAT *)::GetProcAddress("_c_dfDIJoystick2");


The variable name string is taken from the Map file. AFAIK, the underscore prefix is the standard C prefix for symbol names.

However, the pointer is always null and the last error is

1
126: The specified module could not be found.


I would really prefer not to have to copy out the DIDATAFORMAT and all the DIOBJECTDATAFORMAT objects.

The only things I can think of are that the variable is in a DLL other than dinput8.dll or it is defined in the import library.

Looking for a hint.

- tim
Mārtiņš Možeiko
2265 posts / 2 projects
DirectInput variable location
Edited by Mārtiņš Možeiko on
Only public documented symbol that dinput8.dll file exposes is "DirectInput8Create" function. And some other COM related functions.

There are no variables exported. See for yourself - open Visual Studio tools command prompt and run dumpbin /exports on dll file:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
>dumpbin.exe /exports c:\windows\system32\dinput8.dll
Microsoft (R) COFF/PE Dumper Version 12.00.40629.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file c:\windows\system32\dinput8.dll

File Type: DLL

  Section contains the following exports for DINPUT8.dll

    00000000 characteristics
    559F2C20 time date stamp Thu Jul 09 19:21:20 2015
        0.00 version
           1 ordinal base
           5 number of functions
           5 number of names

    ordinal hint RVA      name

          1    0 0000A570 DirectInput8Create
          2    1 00019ED0 DllCanUnloadNow
          3    2 00019FA0 DllGetClassObject
          4    3 00023C50 DllRegisterServer
          5    4 00023EF0 DllUnregisterServer
...

This is all that is exported.
Where did you get map file for dinput?

You are correct about saying that this variable (and other c_XYZ variables mentioned in documentation here https://msdn.microsoft.com/en-us/...ctinputdevice8.setdataformat.aspx) is defined in dinput8.lib library. It is kind of static, kind of dynamic library. Meaning it contains some static library code (to define c_XYZ variables) and to provide DirectInput8Create export for dll file.

So you need to either link with dinput8.lib file, or define this variable on your own (which is not such a bad thing if you don't want to depend on dinput8.lib file). You can probably see how this structure is define in Wine source code. If I'm not mistaken that's exactly what SDL library does.

Btw, you have an error in your code - GetProcAddress takes two arguments, not one.
Timothy McCarthy
52 posts
DirectInput variable location
Edited by Timothy McCarthy on
re: GetProcAddresss - right. I was a bit careless pasting the code in. I've been using Paul DiLascia's WPP code and the call is in a wrapper class that I didn't properly extract for the post. The code works but what I posted is wrong. The actual code is
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
///////////////////////////////////////////////////////////////////////
// WPModule
// Derived from Windows++ by Paul Dilascia
// Class used to represent a Windows module.  
// Essentially, it's just a module instance handle.
///////////////////////////////////////////////////////////////////////
struct WPModule
{
private:
	WPModule(const WPModule& rhs);			// not implemented
	WPModule& operator=(const WPModule& rhs);	// not implemented
public:
	std::string modname;	// module name
	HINSTANCE hinst;	// module handle

	WPModule(HINSTANCE h = 0);
	WPModule(const std::string& nm);
	virtual ~WPModule();

	operator HINSTANCE ()			{return hinst;}
	const std::string& name() const		{return modname;}

	FARPROC getProcAddress(const std::string& procname)
	{
	return ::GetProcAddress(hinst, procname.c_str());
	}
};


The variables are declared in dinput.h as
1
2
3
4
#if(DIRECTINPUT_VERSION >= 0x0500)
extern const DIDATAFORMAT c_dfDIJoystick;
extern const DIDATAFORMAT c_dfDIJoystick2;
#endif /* DIRECTINPUT_VERSION >= 0x0500 */


I did do a dumpbin on the dll for it with the same result as you get. I guess I have to look into the .lib file. There's another tool to dump that I think.

I also wrote a pair of helper stream insertors
1
2
std::ostream& operator <<(std::ostream& os, const DIOBJECTDATAFORMAT& rhs);
std::ostream& operator <<(std::ostream& os, const DIDATAFORMAT& rhs);

because when I looked at the DIDATAFORMAT object the number of object formats defined ia like 164. That was a surprise and why I didn't want to have to make it a local.

I have to see how dependent the code is on dinput8.lib. Sure enough, that's where it is defined and the only undefined symbol. That's got it.

Thanks.

- tim