64Bit dll load issues

Hi team,

I’m having a few problems porting across an app from Win32 to 64 and was hoping for a sanity check.

I have a working Win32 App using a 32bit dll.

I have a new 64bit dll supplied by the manufacturer with a sample supplied application that works.

My 3 line Xojo application fails to run with a 'FunctionNotFound exception.

I’ve had a look with dependency walker and it appears that it can’t find the dll although I’m using a build step to add it in and a build doesn’t work either.

link text

I’ve attached the project, dll in question and the working manufacturer compiled app. While it won’t work without the hardware, it shouldn’t crash!

Any help/advice much appreciated!

stay safe all,
James

Are you sure you are copying the 64 bit DLL?

Hi Kevin,

I’m pretty sure. It’s attached in the linked zip… Unless I’m going crazy!

[quote=496297:@James Mullins]Hi Kevin,

I’m pretty sure. It’s attached in the linked zip… Unless I’m going crazy![/quote]
Have you tried putting the DLL next to your app executable?

Hi Kevin, Yep, it’s sitting right next to it. Exactly the same setup as the Win32 dll so to me this seems very strange…

Hi James,

Thanks for providing a demo of the program, and I have a few questions that may help.

  1. Is the program attempting to load DCDCUsbLib.dll? I am guessing this is 64 bit library?
  2. Here is the code to load a library in Xojo on Windows for Unicode and ANSI

Public Function LoadLibrary(lpLibFileName as String) as Integer #If TargetWindows Declare Function LoadLibraryA Lib "Kernel32.dll" (lpLibFileName as CString) as Integer Declare Function LoadLibraryW Lib "Kernel32.dll" (lpLibFileName as WString) as Integer If IsUnicode Then Return LoadLibraryW(lpLibFileName) Else Return LoadLibraryA(lpLibFileName) End If #Else //System.DebugLog "This is not a Windows OS" Return 0 #Endif End Function

Here is one method to determine if it is running on a Unicode computer (most Windows are Unicode, but I have to ask the question)

Public Function IsUnicode() as Boolean //This performs a test to determine if the computer is unicode (W) or (ANSI) #If TargetWindows Soft Declare function GetDefaultPrinterW Lib "Winspool.drv" (pszBuffer as Ptr, ByRef pcchBuffer as UInt32) as Integer If System.IsFunctionAvailable("GetDefaultPrinterW", "Winspool.drv") Then Return True //Yes, it is Unicode Else Return False //No, it is not unicode End If #EndIf End Function

Here is the code to load the 64-bit library:

Var hLibrary as integer //Handle to the library //Dynamically load the Library - Example hLibrary = LoadLibrary("C:\\Windows\\System32\\User32.dll")

If LoadLibrary successfully loads the dll, then the hLibrary value is a handle value (maybe something like 124590234, etc.). If the library does not load then it returns the value 0 (false). Could you let me know what the value is that is returned for hLibrary?

An added comment, is that some declares are different for 32-bit and 64-bit libraries. There can also be different structures for each pointer, which depends on 32-bit or 64-bit versions.

Lets try to load one function successfully into the library to start, and then go from there :slight_smile:

Edit: Check to make sure that the IDE is building a 64-bit executable with a 64-bit library.

and you have to worry about how structure members are aligned differently in 32 and 64 bit
such a pain in the arse
ran into this myself
https://docs.microsoft.com/en-us/cpp/build/x64-software-conventions?view=vs-2019

Thanks Eugene, I can confirm that I’m on a Unicode Windows build and am building for Win64 with the 64bit dll. I had some trouble understanding your loadlibrary method. I’m guessing you wanted me to add my own function names and dll in place of the kernel32.dll change the function name as well or am I missing something?

The example with kernel32.dll left in runs but returns 0 as a handle when passed the location of my dll.

I agree Norman. This seems tricky!

Thanks again guys.

Attached project if it helps?

Eugene test code

James

Hello James,

I have some good news and some bad news. The good news is that you are programming correctly. The bad news is that the DLL is not compiled properly.

I made an example DLL, compiled it, and it loads properly in the following files.

RAWPLUGINCPLUSPLUSCODE.zip

The custom DLL that I created is called RAWPLUGINCPLUSPLUSCODE.dll and it loads properly. I also added the code to check for system error codes, and the DCDCUsbLib.dll error code is ERROR_MOD_NOT_FOUND (error 126) , and further explanation can be seen here: Debug Error Codes.

I suggest that you contact the creator of the DLL and have them recompile the DLL. :slight_smile:

Thanks very much for your help Eugene, It’s certainly a strange one. The interesting thing is the manufacturer recompiled for me and their C++ app works fine.

The 32bit project is here:

Is there something that would be missing from Xojo that is found in their 64bit compile that I could fix?

They don’t seem to know why it wouldn’t be a straight forward swap of the dll

You mentioned it works with their C++ app. Does the DLL expose the functions with a C interface or C++ interface as I think it has to be a C interface for declares.

Hi Kevin

Thanks for the reply!

Yes. My understanding as they expose C. The 32bit fall works great with Xojo and this was a straight developer recompile for 64bit. No code changes other than select 64 and push go;)

Does the 64 bit c++ app work on the same computer you are testing the declares on?

Could the 64 bit DLL require a later version of the Windows Universal Runtime that isn’t installed on the computer?

Unfortunately yes. They are running side by side in the same folder.

Hi James,

Thanks for the additional information. I loaded the code and it looks like the dll is compatible only for an older version of C++. It is perfectly fine for a C++ dll to be compiled and then used in another C++ program. However, compiling a C++ dll for use in a LLVM compiler does not work, as LLVM does not respect Windows DLL. I am surprised that the 32-bit version works.

I worked for about an hour on the code and there is much more time that is needed, as the current code is setup for 32-bit only and is not 64-bit compatibel. Some of the changes that are needed include:

  1. Code is compiled in an older version of C++, which requires updates
  2. Executable directories need to be changed
  3. Configuration Properties->Linker->Advanced->Target Machine-> MachineX64(/MACHINE:X64)
    and much more.

Sorry, Visual Studio does not have a button that can be clicked to convert from X86 to X64. Much work is needed to make the code 64-bit compatible. The good news is that the current project appears to be configured properly for X86. :slight_smile: Windows 10 respects 32-bit code, so programmers are not in a rush to convert, as Microsoft plays-nice with programmers.

Thanks Eugene,

Really appreciate you help.
I’ve had some correspondence back from the developer.

From the dll developer:

the exports are C not C++ (visible in the h file).
And it is multibyte not unicode if I recall ok - cannot check this now since I am already on holidays and my pc is not with me … But this should not be a problem at this stage, only when you start read write strings it could introduce misalignment in the string content (2 byte per char versus 1).

I can try other ways to compile.

What I produced is rather is a plain C dll exported library with nothing special in it, don’t remember to have set different pragma packs to push alignment but if necessary I can try enforcing other alignments than the default one … I just need to know which one - if You check “pragma pack” you’ll understand what I mean .
If You can get the setup what Eugene used for the example dll correct for xojo I can try the same when I return.

Does the above make sense?

Best,
James

Hello James,

Here are a couple of links to an example github project: RawPlugin, and some explanation to the code: Create a raw d dll for xojo. Maybe this can help the creator.

Warm regards…

This is due to their DLL having a dependency for Microsoft.VC80.CRT 8.0.50727.6195. Their built exe contains a manifest entry for the 64bit version of this dependency but the Xojo built exe does not.

Here is a sample of the manifest from a xojo built exe (yours may vary slightly due to settings):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" manifestVersion="1.0">
  <assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="test dll.exe" type="win32"></assemblyIdentity>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"></supportedOS>
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"></supportedOS>
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"></supportedOS>
</application>
</compatibility>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="False"></requestedExecutionLevel>
      </requestedPrivileges>
    </security>
  </trustInfo>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
<asmv3:application>
<asmv3:windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/pm</dpiAware> <!-- legacy -->
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness> <!-- falls back To pm If pmv2 Is Not available -->
</asmv3:windowsSettings>
</asmv3:application>
</assembly>

This manifest is missing this key part:

  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50727.6195" processorArchitecture="*" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  </dependency>

You can insert this with a post build script using mt.exe from the Windows 10 SDK. I did and all the code you posted above including the loading of the dll at runtime and using standard xojo declares worked as expected:

Declare Function dcdcOpenDevice Lib "DCDCUsbLib.dll" (Timer As UInt32) As UInt8
Dim a As UInt8 = dcdcOpenDevice(1000)
msgbox str(a)

I don’t do enough VS C++ coding to suggest a fix at their end and/or know how to change that requirement but they might have the knowledge to use a more recent version of VS and/or vcrt so I can’t really help any further. I also don’t know why putting the 64b versions of the required vcrt next to the exe doesn’t work, MS must do some magic when using this manifest entry.

2 Likes

VC80.CRT is ancient from VS 2005 or so