Main Restorations Software Audio/Jukebox/MP3 Everything Else Buy/Sell/Trade
Project Announcements Monitor/Video GroovyMAME Merit/JVL Touchscreen Meet Up Retail Vendors
Driving & Racing Woodworking Software Support Forums Consoles Project Arcade Reviews
Automated Projects Artwork Frontend Support Forums Pinball Forum Discussion Old Boards
Raspberry Pi & Dev Board controls.dat Linux Miscellaneous Arcade Wiki Discussion Old Archives
Lightguns Arcade1Up Try the site in https mode Site News

Unread posts | New Replies | Recent posts | Rules | Chatroom | Wiki | File Repository | RSS | Submit news

  

Author Topic: Programming With Ultrastik DLLs on MSYS2  (Read 2233 times)

0 Members and 1 Guest are viewing this topic.

DrakeTungsten

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 287
  • Last login:August 14, 2022, 06:36:45 pm
  • I effed with the wrong person!
    • No Quarter - a basic FE, WIP
Programming With Ultrastik DLLs on MSYS2
« on: June 12, 2017, 04:53:30 pm »
I wrote a front-end, for which I want to add support for uploading Ultrastik maps to the joysticks. I downloaded the DLL package form the Ultimarc site, but am having a problem with the linking step of building my exe.

I am compiling on windows 7, 64-bit, using MSYS2. The SDK from Ultimarc contains 7 folders, most of which which appear to represent various compilers. These folders are:  C#, C++, Delphi, dlls, libsub, VB.net, VB6. Since none of these are specifically for mingw32, I figure my best bet is using whatever's in the generically-named C++ folder.

I copied the two header files in this generically-named C++ file to where my project source files are, and in the main cpp file for my project, I "#include"-ed these files. I then added two more lines to my source file, which I picked up from the Ultimarc documentation:

int deviceCount = UltraStik_Initialize();
UltraStik_Shutdown();

When I "make" the project, the step to create an object file from this works just fine. In case it helps, here is that complete line in my makefile:

g++ -c -g -std=c++0x nq.cpp

But it fails on linking (linking works when I recompile after commenting-out the two Ultrastik functions). Here is my link command in my makefile:

g++ nq.o hbsdl.o nq.res -o nq -static-libgcc -static-libstdc++ `sdl2-config --cflags --libs` -lSDL2_image -lSDL2_ttf -L /c/NoQuarter -lUltraStik64

And the messages I get are:
undefined reference to '__imp__Z2OUltrastik_Initializev'
undefined reference to '__imp__Z18Ultrastik_Shutdownv'

I do have the dll in the folder specified by the "-L /c/NoQuarter" part of the command. If I delete that dll, then I get a different message saying "cannot find Ultrastik64", so the problem is not that it doesn't see the dll.

My googling is telling me that the problem appears to be a mismatch in the way different compilers perform name-mangling, and some folks say it's hopeless to try to link object/library files created by different compilers, while others say that there are tools which should be able to convert the name mangling in one object to be compatible with a compiler other than the one which created it. I'd rather not resort to such tools.  Any advice to get the Ultrastik DLLs to work with what I have? Just to grasp at straws, I tried some of the other DLLs in the SDK download, but no dice.

As an aside, I don't understand the need to link to DLLs. It seems to go against the point of DLLs. But I know my SDL functions also need the DLLs I'm using to be present when I link, so I suppose there's a good reason.









No Quarter - a basic FE, WIP

headkaze

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 2943
  • Last login:August 14, 2023, 02:00:48 am
  • 0x2b|~0x2b?
Re: Programming With Ultrastik DLLs on MSYS2
« Reply #1 on: June 12, 2017, 09:37:57 pm »
I'm the author of the SDK so I should be able to help here :)

Just be aware that internally the name of the dll is actually "UltraStik". I only append the 32/64 to differentiate between the two filenames.

I use Visual Studio to compile them so there may be issues linking them with MinGW. If there is a tool to convert the name mangling I don't see why you can't use one.

As a last resort you can always use LoadLibrary to dynamically load the dll and GetProcAddress to call the actual functions in the dll.

DrakeTungsten

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 287
  • Last login:August 14, 2022, 06:36:45 pm
  • I effed with the wrong person!
    • No Quarter - a basic FE, WIP
Re: Programming With Ultrastik DLLs on MSYS2
« Reply #2 on: June 13, 2017, 10:10:58 pm »
Thanks for the reply. I tried the conversion tools (gendef and dlltool) but they didn't help. I'm sill looking into how to use LoadLibrary and GetProcAddress.
No Quarter - a basic FE, WIP

headkaze

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 2943
  • Last login:August 14, 2023, 02:00:48 am
  • 0x2b|~0x2b?
Re: Programming With Ultrastik DLLs on MSYS2
« Reply #3 on: June 13, 2017, 10:46:40 pm »
Did you take a look at MSVC and MinGW DLLs?

bryhud

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 113
  • Last login:July 16, 2023, 07:08:24 pm
Re: Programming With Ultrastik DLLs on MSYS2
« Reply #4 on: June 15, 2017, 05:55:24 pm »
headkaze, sorry to jump in on this thread but maybe you might be the one to ask on this outside of Andy.

The new king of fighters XIV on steam doesnt work by default with the ultrastiks. Someone had mentioned adding them to the gamecontrollerdb.txt which uses SDL2 configs.

I tried using the SDL2 Gamepad tool but it didnt seem to detect the up and down. I have everything working with the setup below except for up and down. Any thoughts on what setting might work? obviously I was guessing below and it didnt work.

09d21105000000000000504944564944,Ultimarc Ultra-Stik Player 1,a:b0,b:b1,x:b3,y:--BINGO! Either that, or I was attempting to say "before" but it was too many letters to type--,start:b7,leftshoulder:b2,rightshoulder:b5,dpup:a2,dpdown:a3,dpleft:a0,dpright:a1,platform:Windows,
09d21205000000000000504944564944,Ultimarc Ultra-Stik Player 2,a:b0,b:b1,x:--BINGO! Either that, or I was attempting to say "before" but it was too many letters to type--,y:b5,start:b7,leftshoulder:b2,rightshoulder:b5,dpup:a2,dpdown:a3,dpleft:a0,dpright:a1,platform:Windows,

Thanks for any help!

bryhud

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 113
  • Last login:July 16, 2023, 07:08:24 pm
Re: Programming With Ultrastik DLLs on MSYS2
« Reply #5 on: June 15, 2017, 07:20:29 pm »
I figured this out. Sorry.

DrakeTungsten

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 287
  • Last login:August 14, 2022, 06:36:45 pm
  • I effed with the wrong person!
    • No Quarter - a basic FE, WIP
Re: Programming With Ultrastik DLLs on MSYS2
« Reply #6 on: June 15, 2017, 08:53:10 pm »
Yes, I saw that link. That's what lead me to try using gendef and dlltool. That link talks about a tool called pexports, but it wasn't installed on my msys2 install, and further research showed that gendef, which I did already have installed, does the same thing. Using the file created by these two tools gives me the same error. The other method, of using the reimp tool, successfully created another file which is supposed to be a MINGW compatible library, but linking against that library also gives me the same undefined reference errors I originally had.

I tried wrapping the two header files inside an 'extern "C"' block, but that resulted in the linker complaining about conflicting definitions. I think that's because the functions which had conflicting definitions are overloaded functions, so they require name mangling so they can be differentiated.

I haven't got around to trying GetProcAddress yet. It sounds like I need to know the name MSVC mangled the functions into, and I haven't found that yet. If that route doesn't work, I recall seeing that the Ultramap program is supposed to be able to upload maps from the command line, so if that can work without launching the Ultramap GUI, I can just build a command line for it and run it with a process call.

« Last Edit: June 15, 2017, 09:27:19 pm by DrakeTungsten »
No Quarter - a basic FE, WIP

headkaze

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 2943
  • Last login:August 14, 2023, 02:00:48 am
  • 0x2b|~0x2b?
Re: Programming With Ultrastik DLLs on MSYS2
« Reply #7 on: June 16, 2017, 02:58:32 am »
I haven't got around to trying GetProcAddress yet. It sounds like I need to know the name MSVC mangled the functions into.

No, you don't need to know the "mangled" function names. Just use the real ones as presented in the header file.

Here is an example of how MAME uses LoadLibrary/GetProcAddress for Raw Input.

Code: [Select]
// RawInput APIs
typedef /*WINUSERAPI*/ INT (WINAPI *get_rawinput_device_list_ptr)(OUT PRAWINPUTDEVICELIST pRawInputDeviceList, IN OUT PINT puiNumDevices, IN UINT cbSize);
typedef /*WINUSERAPI*/ INT (WINAPI *get_rawinput_data_ptr)(IN HRAWINPUT hRawInput, IN UINT uiCommand, OUT LPVOID pData, IN OUT PINT pcbSize, IN UINT cbSizeHeader);
typedef /*WINUSERAPI*/ INT (WINAPI *get_rawinput_device_info_ptr)(IN HANDLE hDevice, IN UINT uiCommand, OUT LPVOID pData, IN OUT PINT pcbSize);
typedef /*WINUSERAPI*/ BOOL (WINAPI *register_rawinput_devices_ptr)(IN PCRAWINPUTDEVICE pRawInputDevices, IN UINT uiNumDevices, IN UINT cbSize);

// RawInput variables
static get_rawinput_device_list_ptr     get_rawinput_device_list;
static get_rawinput_data_ptr            get_rawinput_data;
static get_rawinput_device_info_ptr     get_rawinput_device_info;
static register_rawinput_devices_ptr    register_rawinput_devices;

...
HMODULE user32;

// look in user32 for the raw input APIs
user32 = LoadLibrary(TEXT("user32.dll"));
if (user32 == NULL)
goto error;

// look up the entry points
register_rawinput_devices = (register_rawinput_devices_ptr)GetProcAddress(user32, "RegisterRawInputDevices");
get_rawinput_device_list = (get_rawinput_device_list_ptr)GetProcAddress(user32, "GetRawInputDeviceList");
get_rawinput_device_info = (get_rawinput_device_info_ptr)GetProcAddress(user32, "GetRawInputDeviceInfo" UNICODE_SUFFIX);
get_rawinput_data = (get_rawinput_data_ptr)GetProcAddress(user32, "GetRawInputData");
if (register_rawinput_devices == NULL || get_rawinput_device_list == NULL || get_rawinput_device_info == NULL || get_rawinput_data == NULL)
goto error;
osd_printf_verbose("RawInput: APIs detected\n");

// get the number of devices, allocate a device list, and fetch it
if ((*get_rawinput_device_list)(NULL, &device_count, sizeof(*devlist)) != 0)
goto error;
if (device_count == 0)
goto error;
devlist = global_alloc_array(RAWINPUTDEVICELIST, device_count);
if ((*get_rawinput_device_list)(devlist, &device_count, sizeof(*devlist)) == -1)
goto error;

...

No too difficult is it?