0

I am trying to create a C wrapper DLL to interface a commercial DLL written with the CDECL calling convention, so that it can be interfaced with existing programs written in Excel VBA (hence using STDCALL calling convention).

I have exactly the same issue, probably after trying very similar things. I have tried using mingw (gcc & g++, 32 & 64 bits), and cygwin gcc flavors (gcc & g++ 32 & 64 bits). No luck.

I suspect an issue with the compilation or linker, as some combinations of compiler produce DLL that are just not recognized by VBA (although they can be called by a stub exe) throwing an error 53-DLL not found. Other combination give another error (48-error loading DLL), of course with the very same code.

I am using Windows 10 64 bits with Office 64 bits.

This is wrapper.c:

#include "wrapper.h"
#include <windows.h>
#include <stdio.h>

#ifdef cplusplus
extern "C"
{
#endif

PCNC_EXPORT void __stdcall WrFreeString(char* str)
{
    //Memory
    return FreeString(str);
}
PCNC_EXPORT int __stdcall WrGetVer()
{
    return GetVer();
}
PCNC_EXPORT char* __stdcall WrGetLibPath()
{
    return GetLibPath();
}

// snip ___


PCNC_EXPORT BOOL __stdcall DllMain(HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

#ifdef cplusplus
}
#endif

wrapper.h:

#include "PlanetCNCLib.h"
#include "PlanetCNCLibTypeDef.h"

#ifdef cplusplus
extern "C"
{
#endif

PCNC_EXPORT void __stdcall WrFreeString(char* str);
PCNC_EXPORT int __stdcall WrGetVer();
PCNC_EXPORT char* __stdcall WrGetLibPath();

#ifdef cplusplus
}
#endif

from PlanetCNCLib.h:

#ifndef __PlanetCNCLib_H__
#define __PlanetCNCLib_H__


#include "PlanetCNCLibTypeDef.h"


#ifdef __cplusplus
extern "C" {
#endif


#ifndef PCNC_EXPORT
#   ifdef _WIN32
#       define PCNC_EXPORT __declspec(dllexport)
#   else
#       define PCNC_EXPORT __attribute__((visibility("default"))) 
#   endif
#endif

// etc

And the Makefile:

#CPP=/usr/bin/i686-w64-mingw32-g++.exe   # doesnt work (err 48 err loading DLL)
#CPP=/usr/bin/x86_64-w64-mingw32-g++.exe # doesnt work (err 53 DLL not found)
#CPP=/usr/bin/i686-pc-cygwin-g++         # doesnt work (err 48 err loading DLL) 
#CPP=/usr/bin/x86_64-pc-cygwin-g++.exe   # doesnt work (err 53 DLL not found)
#CPP=gcc                                 # doesnt even compile

#LD=/usr/bin/i686-w64-mingw32-ld.exe
#LD=/usr/bin/x86_64-w64-mingw32-ld.exe
LD=$(CPP)

LDFLAGS=-shared -L/usr/lib -L./lib/ -Wl,--add-stdcall-alias #--kill-at
CFLAGS=-c

all: PlanetCNCWrapper.dll

wrapper.o:PlanetCNCLib.h PlanetCNCLibTypeDef.h wrapper.c
    $(CPP) -o $@ wrapper.c  $(CFLAGS)

PlanetCNCWrapper.dll:wrapper.o
    $(LD) $(LDFLAGS) -o $@ $? -L./lib/ lib/PlanetCNCLib64.lib -lPlanetCNCLib64 

clean:
    rm -f *.o *.e *~ .*~ *stackdump PlanetCNCWrapper.dll

Other useful data:

Windows Version 1909 (OS Build 18363.778)
System type: 64-bit operating system, x64-based processor
Microsoft Excel for Office 365 MSO (16.0.11929.20708) 64 bits
i686-w64-mingw32-g++ (GCC) 9.2.0
x86_64-w64-mingw32-g++ (GCC) 9.2.0
i686-pc-cygwin-g++ (GCC) 6.4.0
x86_64-pc-cygwin-g++ (GCC) 9.3.0

Forgot to add that the --add-stdlib-alias doesn't seem to do anything: symbols get decorated in the DLL regardless of the presence of this flag.

alain R
  • 11
  • 1
  • https://stackoverflow.com/questions/26103966/how-can-i-statically-link-standard-library-to-my-c-program – Hans Passant Apr 27 '20 at 11:58
  • Your wrapper needs to declare functions from PlanetCNCLib64.dll as dllimport, but declare its own wrapper functions as dllexport when building the DLL, so hijacking the `PCNC_EXPORT` macro in the wrapper is not a good idea. You need your own macro. It's not clear from your posted PlanetCNCLib.h extract how the user of PlanetCNCLib64.dll is supposed to declare the functions as dllimport. – Ian Abbott Apr 27 '20 at 12:24
  • Hello Ian, thanks for your anszer. Actually PCNC_EXPORT resolves to __declspec(dllexport) in the context of my code, which I use to declare my own export function in my wrapper (actually same name as the PlanetCNC ones but prefixed with Wr). I'll check tonight what the headet does in this context, I would have though it imports the PlanetCNC original functions but I'll double check. This doesn't address the fact that the DLL isn't recognized or loadable by VBA, does it ? – alain R Apr 27 '20 at 13:41
  • @HansPassant: do you think that static linking of the PlanetCNC DLL would help ? – alain R Apr 27 '20 at 13:44
  • You can't forget to deploy the C runtime library that way, most likely the real problem. – Hans Passant Apr 27 '20 at 13:51
  • @HansPassant I'll test it out tonight but the PlanetCNC software works on my system, without having to deploy any runtime. And I am not calling any other function but the PlanetDLL ones in my DLL, it is just a wrapper. – alain R Apr 27 '20 at 15:23

0 Answers0