I have a Windows 10 64-bits, Office 2013 32-bits and using MinGW64.
I followed instructions from https://www.transmissionzero.co.uk/computing/building-dlls-with-mingw/
I checked other answers threads in stackoverflow without success.
When I run Excel VBA code I get the follow error: "Run-Time error 48: File not found", but the file is in the folder and the folder has PATH reference.
I have the Add.c with follow code:
#include "add.h"
#include <windows.h>
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
/* Code path executed when DLL is loaded into a process's address space. */
break;
case DLL_THREAD_ATTACH:
/* Code path executed when a new thread is created within the process. */
break;
case DLL_THREAD_DETACH:
/* Code path executed when a thread within the process has exited *cleanly*. */
break;
case DLL_PROCESS_DETACH:
/* Code path executed when DLL is unloaded from a process's address space. */
break;
}
return TRUE;
}
int ADDCALL Add(int a, int b)
{
return (a + b);
}
/* Assign value to exported variables. */
int foo = 7;
int bar = 41;
The follow Add.h code:
/* add_var.h
Declares a function and variables to be imported by our application, and
exported by our DLL.
*/
/* You should define ADD_EXPORTS *only* when building the DLL. */
#ifdef ADD_EXPORTS
#define ADDAPI __declspec(dllexport)
#else
#define ADDAPI __declspec(dllimport)
#endif
/* Define calling convention in one place, for convenience. */
#define ADDCALL __cdecl
/* Make sure functions are exported with C linkage under C++ compilers. */
#ifdef __cplusplus
extern "C"
{
#endif
/* Declare our Add function using the above definitions. */
ADDAPI int ADDCALL Add(int a, int b);
/* Exported variables. */
extern ADDAPI int foo;
extern ADDAPI int bar;
#ifdef __cplusplus
} // __cplusplus defined.
#endif
And the follow VBA code to test:
Option Explicit
Private Declare PtrSafe Function Add Lib "C:\exceladd2\AddLib.dll" (ByVal a As Integer, ByVal b As Integer) As Integer
Sub Test()
Call MsgBox(Add(4, 5))
End Sub
The follow code was compiled with MinGW64 without errors or warnings:
x86_64-w64-mingw32-gcc-8.1.0 -c -o add.o add.c -D ADD_EXPORTS
x86_64-w64-mingw32-gcc-8.1.0 -o AddLib.dll add.o -shared -s -Wl,--subsystem,windows,--kill-at
The follow is the result from dependencies check from the library: https://pasteboard.co/J4zegPO.jpg
I tried to compile with gcc 32 bits and other versions of gcc 64-bits and got the same error 48 in Excel.
On the past I was able to run similar DLL compiled with gcc 32-bits in a Windows 7 32-bits with Office 2010 32-bit without any trouble. Ran Excel VBA with and without PtrSafe without result.
Is there anything wrong with code or compile?
Do you know any software to troubleshoot DLLs?
Thanks in advance for your help!
Related
I plan on building several libraries following the FIPS standards (hashing, encryption). I want to have several batch/bash scripts that will automate the building process of these libraries for every desktop platforms (Windows, Mac, Linux). I plan on using MinGW's port of gcc on Windows and simply gcc on Linux or Mac.
My code for the library is the following:
hash.h
#ifndef HASHH
#define HASHH
#ifdef STATIC
#define ADDAPI
#define ADDCALL
#define EXTERN extern
#else
#define EXTERN
#ifdef _WIN32
#ifdef BUILD
#define ADDAPI __declspec(dllexport)
#else
#define ADDAPI __declspec(dllimport)
#endif
#define ADDCALL __cdecl
#else
#define ADDAPI
#define ADDCALL
#endif
#endif
/*** The sha3-256 hash function.
#param buffer The buffer containing the data to be hashed.
#param length The length of the buffer.
#param digest The hash of the data in buffer.
*/
ADDAPI EXTERN int ADDCALL sha3_256(unsigned char* buf, unsigned long len, unsigned char* digest);
#endif
hash.c
#include "hash.h"
int sha3_256(unsigned char* buf, unsigned long len, unsigned char* digest){
return len * 2;
}
For DLL target on Windows I do:
gcc -c -D BUILD source\hash.c -oobjects\hash.o
ld -s -shared objects\hash.o -ohash.dll
For static target I do:
gcc -c -D STATIC source\hash.c -oobjects\hash.o
ar rcs hash.lib objects\hash.o
Everything works fine for building but when I use the header in a program the ADDAPI and ADDCALL macros are never defined for static building. This is due to the STATIC macro never initialized. I would like that this same header works for both building and using in client apps. I would also like that the macros allow to build both for dll target than for static lib target without the client having to pass a macro on the command line for it to work.
Do you have any idea if this is possible?
If it is, how would you go about doing this?
With the above code both building static and dll works but for client only dll works because for static I need to pass the STATIC macro on the command line. I want an option to prevent that.
I am in the process of refactoring some old legacy code, written in C. The code is very tightly coupled and I am struggling to refactor it into clear logical, loosely coupled modules.
In my early iterations, I have managed to ascertain logical modules - however the tight coupling is causing me problems, as many of the functions have intimate knowledge of other parts of the system.
The way I intend to fix this is to use extern declarations. The pseudocode below hopefully, explains the situation:
Assume I have two logically separate modules Foo and FooBar. Each module is to be built into a separate library (the FooBar module has a dependency on the Foo module).
/*######################################*/
/* Foo Module */
/*######################################*/
/* Foo.h */
#ifndef FOO_MODULE_H
#define FOO_MODULE_H
void foo(int id);
int do_something();
...
#endif /* FOO_MODULE_H */
/* Foo.c */
#include "Foo.h"
extern int foobar(); /* defined in FooBar module (a separate library) */
void foo(int id){
int var;
switch (id){
case 1:
var = do_something();
break;
case 2:
/* the module that gets here, has the required functions defined in it */
var = foobar();
}
return var;
}
/*###############################*/
/* FOOBar module */
/*###############################*/
/* FooBar.h */
#ifndef FOOBAR_MODULE_H
#define FOOBAR_MODULE_H
#include "Foo.h"
int foobar();
void do_something_else();
...
#endif /* FOOBAR_MODULE_H */
/* source file */
int foobar(){
return 42;
}
void do_something_else(){
int ret = foo(2);
printf("Function returned: %d", ret);
}
Is this a valid way to refactor the existing code into logically separate modules whilst allowing executables that link to libfoo.so and libfoobar.so to continue to work correctly?
My underlying assumption is that modules that link to libfoo.so only will not be able to resolve foobar() - but that should be fine since they do not need that function, so they will never have to call it. On the other hand, for modules that link to libfoobar.so, when they call foo(), `foobar() would have been resolved (the function definition is in the module).
Will the scheme I describe above work as I expect, or is there some gotcha that I am missing?
I tried your to compile your files into shared libs and then use them (I use cygwin).
Here's for Foo:
cm#Gregor-PC ~/src
$ gcc -I. -c --shared -o libFoo.so Foo.c
With the bin util nm you can check the symbols (grep for 'foo' to limit the output)
cm#Gregor-PC ~/src
$ nm libFoo.so | grep foo
0000000a T _foo
U _foobar
Where it gives an offset and says 'T' for terminated that tells you the symbol is defined in the lib.
Now the FooBar lib has to linked against Foo in order to have the foo symbol
cm#Gregor-PC ~/src
$ gcc -I. -L. --shared -o libFooBar.so FooBar.c libFoo.so
cm#Gregor-PC ~/src
$ nm libFooBar.so | grep foo
61f0111e T _foo
61f010e0 T _foobar
With this I can compile against FooBar only and get foo as a known symbol:
cm#Gregor-PC ~/src
$ gcc -I. -o tst1 tst1.c libFooBar.so
cm#Gregor-PC ~/src
$ ./tst1
Function returned: 42
So it seems to work OK.
You can improve on your approach to modularize your C code by having header files that contain only public data types, exported function prototypes (declared as extern) and maybe even public global variables or constants. Such a header file declares the interface to the module and would have to be included where the module is used.
This is explained with much more detail in the wonderful book 'Functional C' (Hartel, Muller, 1997, Addison Wesley, link ) in the chapter on modules.
The benefit is that your dependencies are clearer to see (as includes in the source files) and you don't have to have that unsightly extern declaration in the Foo source.
For your example:
/* Foo.h */
extern int foo(int id); /* exported to FooBar */
/* FooBar.h */
extern int foobar(); /* export to Foo */
extern void do_something_else(); /* export to tst1 */
/* Foo.c */
#include <Foo.h>
#include <FooBar.h>
int do_something() {
return 11;
}
int foo(int id){
int var;
switch (id){
case 1:
var = do_something();
break;
case 2:
/* the module that gets here, has the required functions defined in it */
var = foobar();
}
return var;
}
/* FooBar.c */
#include <stdio.h>
#include <Foo.h>
#include <FooBar.h>
int foobar(){
return 42;
}
void do_something_else(){
int ret = foo(2);
printf("Function returned: %d", ret);
}
I can compile DLLs properly using mingw and do the exports/imports stuff. What I am looking for is defining the dll onload function properly as you would in MS VC products. Google didn't turn up anything. Anyone have any ideas or a link to a tutorial?
Okay, so after some fiddling...it's working. For anyone else that is having issues here it is. My issues weren't related to compiling in instead of loading dynamically. It was a mash-up of a couple of tutorial/question/how-tos that got me to this point.
dll.c
#include <stdio.h>
#include <windows.h>
#include "dll.h"
//extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD Reason, LPVOID LPV) {
//This one was only necessary if you were using a C++ compiler
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
// Code to run when the DLL is loaded
printf ("Load working...\n");
break;
case DLL_PROCESS_DETACH:
// Code to run when the DLL is freed
printf ("Unload working...\n");
break;
case DLL_THREAD_ATTACH:
// Code to run when a thread is created during the DLL's lifetime
printf ("ThreadLoad working...\n");
break;
case DLL_THREAD_DETACH:
// Code to run when a thread ends normally.
printf ("ThreadUnload working...\n");
break;
}
return TRUE;
}
EXPORT void hello(void) {
printf ("Hello\n");
}
dll.h
#ifndef DLL_H_
#define DLL_H_
#ifdef BUILD_DLL
/* DLL export */
#define EXPORT __declspec(dllexport)
#else
/* EXE import */
#define EXPORT __declspec(dllimport)
#endif
EXPORT void hello(void);
#endif /* DLL_H_ */
hello.c
#include <windows.h>
#include <stdio.h>
int main () {
/*Typedef the hello function*/
typedef void (*pfunc)();
/*Windows handle*/
HANDLE hdll;
/*A pointer to a function*/
pfunc hello;
/*LoadLibrary*/
hdll = LoadLibrary("message.dll");
/*GetProcAddress*/
hello = (pfunc)GetProcAddress(hdll, "hello");
/*Call the function*/
hello();
return 0;
}
when compiled with
gcc -c -DBUILD_DLL dll.c
gcc -shared -o message.dll dll.o -Wl,--out-implib,libmessage.a
gcc -c hello.c
gcc -o hello.exe hello.o message.dll
produces the expected output of
Load working...
Hello
Unload working...
Since mingw is just a windows port of GCC and associated tools, you can use GCC constructor and destructor attributes. These work for both shared and static libraries, and execute code before and after main is run, respectively. Additionally, you can specify multiple constructor and destructor functions per library.
static void __attribute__((constructor))
your_lib_init(void)
{
fprintf(stderr, "library init\n");
}
static void __attribute__((destructor))
your_lib_destroy(void)
{
fprintf(stderr, "library destroy\n");
}
I'm doing some test to learn how to create shared library.
The template for shared libraries in Code::Blocks is this
library.c
// The functions contained in this file are pretty dummy
// and are included only as a placeholder. Nevertheless,
// they *will* get included in the shared library if you
// don't remove them :)
//
// Obviously, you 'll have to write yourself the super-duper
// functions to include in the resulting library...
// Also, it's not necessary to write every function in this file.
// Feel free to add more files in this project. They will be
// included in the resulting library.
// A function adding two integers and returning the result
int SampleAddInt(int i1, int i2)
{
return i1 + i2;
}
// A function doing nothing ;)
void SampleFunction1()
{
// insert code here
}
// A function always returning zero
int SampleFunction2()
{
// insert code here
return 0;
}
I tried to compile it, and it compiled without any error or warning. But when i tried to use it with the ctyped.cdll.LoadLibrary("library path.dll") in python 3(that actually should work like the C function), it said that it wasn't a valid win32 application. Both python and code::blocks are 32 bit (code:blocks compile with gcc, and i tryed to use an installed version of mingw on my system, but it gives some error about a missing library) while i'm working on win 7 64bit
Do you know what the problem can be, or if i'm doing something wrong?
EDIT1:
i'm on windows 7 64bit, in the specs file of the compiler is wrote: "Thread model: win32, gcc version 3.4.5 (mingw-vista special r3)"
and i used as command
gcc.exe -shared -o library.dll library.c
in python i used
from ctypes import *
lib = cdll.LoadLibrary("C:\\Users\\Francesco\\Desktop\\C programmi\\Python\\Ctypes DLL\\library.dll")
and the error was
WindowsError: [Error 193] %1 is not a valid Win32 application
i installed both python3.1 and mingw from the binary package and not compiling them on my system
EDIT2:
After reading Marc answer.
main.h
#ifndef __MAIN_H__
#define __MAIN_H__
#include <windows.h>
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C"
{
#endif
DLL_EXPORT int MySimpleSum(int A, int B);
#ifdef __cplusplus
}
#endif
#endif // __MAIN_H__
main.c
#include "main.h"
// a sample exported function
DLL_EXPORT int MySimpleSum(int A, int B)
{
return A+B;
}
compiling options
gcc -c _DBUILD_DLL main.c
gcc -shared -o library.dll main.o -Wl,--out-implib,liblibrary.a
with gcc 4.5.2
still get the same error..
I believe in the windows environment you need to use the __declspec annotation. How to create a shared library and the use of __declspec is described here: DLL Creation in MingW.
I have following function defined in one dll:
__declspec( dllexport ) int __stdcall
mjscall(char *cmd, DWORD wtime, char *stdoutfile, char *stderrfile )
I need to write one process to call the above function.
I am doing it first time,I do not have much idea.
I have written the following code
#include <windows.h>
#include <windows.h>
#include <stdio.h>
#include <io.h>
#include <stdlib.h>
#include <limits.h>
extern __declspec( dllexport ) int __stdcall mjscall(char *cmd, DWORD wtime, char *stdoutfile, char *stderrfile );
typedef INT (*MJSCALL) (char *,DWORD, char *, char *);
int main()
{
char *a,*b,*c;
a=NULL;
b=NULL;
c=NULL;
DWORD aa =1;
int i;
HMODULE hLib;
MJSCALL ADD;
hLib=LoadLibrary("f3cucall.dll");
if(hLib==NULL)
{
return 1;
}
ADD=(MJSCALL)GetProcAddress(hLib,"mjscall");
if (ADD==NULL)
{
return 1;
}
(ADD)(a,aa,b,c);
return 0;
}
The "(ADD)(a,aa,b,c);" is causing the problem.
Can somebody help me out?
I think you mixed two things up:
the __declspec(dllexport) MSVC keyword exports functions from a DLL (tells the linker to do so), and the __declspec(dllimport) imports functions from a DLL. This is done at loading time, the linker will create all the necessary code to load the DLL and resolve the symbol. In fact, it adds some code to the exe to let the OS load the DLL. You can use functions declared with __declspec(dllimport) just like any normal internal function.
If you want to use this approach, you need the DLL's lib file, since it contains information for the linker to resolve the symbolic name. It doesn't actually contain code, only these information on the DLL for the linker. Additionally, you have to tell the linker that the function you want to use is located at a DLL, using the magic __declspec(dllimport) before the function declaration. That's why you provide a .lib and a header file (containing these declarations) with your DLL if you want to do it this way. You should rebuild the project that uses the DLL when you change the DLL, as the .lib file may have changed.
You can use the same header file in your DLL project and the projects that import from this DLL:
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
MYDLL_API void printMe(int);
The MyDLL_API get resolved to either __declspec(dllexport) (in the DLL project, where you define the MYDLL_EXPORTS in the project settings) or __declspec(dllimport) (in all projects that use the dll). This way, you only need one header file for the DLL.
Another method of calling DLL functions is to use LoadLibrary and GetProcAdress. These two are used to load a DLL at runtime. The main difference between loading a DLL at loading time and at runtime is that you have some control over loading the DLL at runtime, whereas the OS will do the job when the DLL is to load at loading time (e.g. show a message box if the DLL cannot be found and do not run the process).