How do I link a library (.dll and/or .lib) to my mex code?

I've been working with a company and given three files: a header file (.h), a static library (.lib), and a dynamic library (.dll). The header file has 22 functions written in C++. The static library unzips into 22 dynamic libraries, none of which can be read with notepad nor unzipped with 7-Zip. The main dynamic library can be unzipped, but these files contain .rsrc and .data files that cannot be read with notepad. The company will not give me the source code.
With that being said, I have to implement the 22 functions with MATLAB. I've written 22 mex files but I do not know how to link anything other than the header file to the mex file. I've tried
mex '-LC:\Program Files\MyPath\MyFolder' -lMyLibMinusLibExtension myfun.cpp
It instead gives me five errors saying " skipping incompatible" and then ending with " cannot find -lMyLibMinusLibExtension"
I've also tried using loadlibrary, but it shows this thunk-related error:
Error using loadlibrary
Building MyLibMinusLibExtension_thunk_pcwin64 failed. Compiler output is:
C:\TDM-GCC-64\bin\gcc -I"C:\Program
Files\MATLAB\R2017a\extern\include" -fexceptions
-fno-omit-frame-pointer -I"C:\Program Files\MyPath\MyFolder"
-I"C:\Program Files\MyPath\MyFolder" "MyLibMinusLibExtension_thunk_pcwin64.c"
-o "MyLibMinusLibExtension_thunk_pcwin64.dll" -shared
If anyone can let me know how I'm supposed to link either the .dll or the .lib (or both, I'm not really sure which one is needed or how I'm supposed to check) to my mex files or straight to my MATLAB code, that would be very helpful.

2 Kommentare

There should be more error output for the loadlibrary call. The line you gave is the compiler command without the actual error output.
Mandeguz
Mandeguz am 12 Jul. 2017
Bearbeitet: Mandeguz am 12 Jul. 2017
This is the error output (for some reason I did not catch that the first time):
In file included from MyLibMinusLibExtension_thunk_pcwin64.c:27:0:
C:\Program Files\MyPath\MyFolder/MyLibMinusLibExtension.h:60:9: error:
expected ';', ',' or ')' before '&' token
int & errorCode /** Pump error field */,
^
C:\Program Files\MyPath\MyFolder/MyLibMinusLibExtension.h:31:57: error:
expected ';', ',' or ')' before '&' token
int &
out_one,
^
C:\Program Files\MyPath\MyFolder/MyLibMinusLibExtension.h:32:80: error:
expected ';', ',' or ')' before '&' token
float &
output);
^
In file included from MyLibMinusLibExtension_thunk_pcwin64.c:27:0:
C:\Program Files\MyPath\MyFolder/MyLibMinusLibExtension.h:37:62: error:
expected ';', ',' or ')' before '&' token
unsigned
int
&
value
);
^
All of these errors stem from failing to read C++, even with the "extern C". Examples of what happens when I turn the ampersands into asterisks is below ( or here )

Melden Sie sich an, um zu kommentieren.

Antworten (2)

Guillaume
Guillaume am 10 Jul. 2017

1 Stimme

The static library unzips into 22 dynamic libraries
The main dynamic library can be unzipped
Huh? Neither static library (.lib) nor dynamic library (.dll) are zip files. They just contain code and you shouldn't be able to unzip them into anything. Both should just contain the (mostly compiled for lib/ fully compiled for dll) code for the 22 functions defined by the header file.
It does not sound like the files you've been given are genuine dll or lib files. I can't even understand why unzipping something positing as a static library would result in dll files.
Note that if the code is genuinely C++, you will not be able to use it from matlab which can only speak C. If any of the 22 exported function use any class or non-pod type in their signature or throw exceptions, then you're in trouble. All exported functions must be surrounded by an extern "C"{...} in the header file.

7 Kommentare

Mandeguz
Mandeguz am 10 Jul. 2017
Bearbeitet: Mandeguz am 11 Jul. 2017
I thought that was weird too, but I've never dealt much with .dlls or .libs before, so I just tried unzipping them to see what I would get and I got what I described above. All unzippings were through 7-zip, and all unzippable files were unreadable junk beforehand.
As far as the C++ header goes, the only C++ thing is that there are variables passed via reference (like this):
#ifdef __cplusplus
extern "C" {
#endif
extern MY_DLL_API BOOL myfun(unsigned int in_one, unsigned int & in_two);
#ifdef __cplusplus
}
#endif
See how in_two is passed not by pointer but is referenced inside the function? The unsigned int & allows this to occur. This is a strictly C++ thing.
Now both #ifdef _cplusplus_ statements are mine, which I placed in there after reading that was a solution by many MATLAB coders out there. Unfortunately, it did not solve my problem, as described above. extern "C" was already there as well. So I don't think I'm in too much trouble as long as I figure out how to link my mex files to their corresponding libraries.
James Tursa
James Tursa am 10 Jul. 2017
Bearbeitet: James Tursa am 10 Jul. 2017
What does the actual header look like directly from the vendor, without any of your additions or embellishments? E.g., for the myfun function.
Mex routines can be C++ and call C++ code, but if the function signatures are not extern "C" and you are not using exactly the same compiler you may run into name mangling/decoration issues that will cause unresolved external link errors.
My note about C++/C is only if you call the code directly from matlab. Your mex file can indeed call C++ libraries. However because C++ does not define the binary layout, calling C++ dll/lib from other C++ code is extremely risky if library and calling code have not been compiled at the same time by the same compiler with the same settings. Best case, it will be obvious and crash.
If the header already came with extern "C" then the interface is C anyway, so there's no issue.
A possible reason why you're getting an error while linking the lib file is that it's been compiled as 32 bit whereas you're compiling 64 bit code. If that is the case, you're in trouble. You won't be able to use the lib (other than with 32 bit mex only usable with 32 bit matlab which is not available in recent versions). Your only workaround would be to write a 32 bit executable that loads the dll and relay all the dll inputs/outputs to the mex through interprocess communication. See accessing 32 bit dlls from 64 bit code
While the company I've been working with has given me the h, dll, and lib files, I unfortunately do not have permission to share any of these files publicly nor the name of the company I am working with, hence, the name alterations. I've tried swapping out only names so that I can address the problem without breaking contract, although I've unfortunately had a few typos in the past (James Tursa, you have seen this before with the referenced variable I forgot).
This is the best I can do (you may recognize the read function I was working on):
#pragma once
#include <windows.h>
#include "WinDef.h" //include BOOL definition
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the DLL_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// DLL_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
extern "C" {
typedef enum{ Y = -1,Z = 0,
A = 1, B = 2, C = 3,
D = 4, E = 5, F = 6, G = 7} state;
extern DLL_API unsigned int start();
extern DLL_API BOOL semistart(unsigned int in_one, unsigned int in_two);
extern DLL_API BOOL stop(unsigned int in_one,unsigned int in_two);
extern DLL_API BOOL semistop(unsigned int in_one, unsigned int in_two);
extern DLL_API void small_one();
extern DLL_API BOOL small_two();
extern DLL_API BOOL fun_one(unsigned int in_one);
extern DLL_API BOOL fun_two(unsigned int in_one);
extern DLL_API const char * str_one(unsigned int in_one);
extern DLL_API const char * str_two(unsigned int in_one);
extern DLL_API BOOL grab_one(unsigned int in_one, int & out_one, int & out_two, int & out_three);
extern DLL_API BOOL grab_two(unsigned int in_one, unsigned int in_two, float & output);
extern DLL_API BOOL go_one(unsigned int in_one, unsigned int in_two, float in_three);
extern DLL_API BOOL go_two(unsigned int in_one, unsigned int in_two, float in_three);
extern DLL_API BOOL go_three(unsigned int in_one, unsigned int in_two, float in_three);
extern DLL_API BOOL interrupt(unsigned int in_one, unsigned int in_two);
extern DLL_API BOOL read(unsigned int in_one, unsigned int & value);
extern DLL_API BOOL write(unsigned int in_one, unsigned int value);
extern DLL_API BOOL big_function(unsigned int in_one, unsigned int in_two,
int & stat_one, int & stat_two,
float & data_one, float & data_two, float & data_three);
}
I will look into seeing if the dll is 32-bit, and if so, use an IPC (as linked by Guillaume) to have MATLAB properly communicate with it.
Side note: by 22 functions I meant 19 (bad at counting).
Thanks
Maybe try something simple. Copy the lib file (let's call it mylib.lib) to the same folder as your myfun.cpp file. Then do this:
mex myfun.cpp mylib.lib
Do you get unresolved link errors?
This error occured when running mex myfun.cpp mylib.lib
Error using mex
C:\Users\mandeguz\AppData\Local\Temp\mex_25457491823753_5228\myfun.obj:myfun.cpp:(.text+0x103):
undefined reference to `__imp_myfun'
collect2.exe: error: ld returned 1 exit status
And when I change the header file as Philip Borghesani suggested,
Error using mex
C:\Users\mandeguz\AppData\Local\Temp\mex_28574022828818_5228\myfun.obj:myfun.cpp:(.text+0x103):
undefined reference to `__imp_myfun'
collect2.exe: error: ld returned 1 exit status
And when I change it back,
Error using mex
C:\Users\mandeguz\AppData\Local\Temp\mex_28775562444849_5228\myfun.obj:myfun.cpp:(.text+0x103):
undefined reference to `__imp_myfun'
collect2.exe: error: ld returned 1 exit status
which makes me think that the long number next to Temp\mex_ is memory-based, since that's the only thing that changes when I change the references into pointers. I'm not really sure what this message means, but I read somewhere that _imp__ is a pointer that is defined in a .lib file. I'll look more into this.
The DLLs were in 32-bit, just found out

Melden Sie sich an, um zu kommentieren.

Philip Borghesani
Philip Borghesani am 11 Jul. 2017

1 Stimme

The reference parameters will not work with loadlibrary because c does not support the "&" reference c++ syntax. To load this library using loadlibrary make a copy of the header file and change all & symbols in function declarations to * pointer symbols. The resulting header should be usable by MATLAB to load the library.

1 Kommentar

Great point, I think that has the potential to be a huge issue. Unfortunately, I think that since the source code was compiled with C++, I might be in a tough situation because I can't actually change that function, only its inputs.
This error occured when running loadlibrary('mylib')
Error using loadlibrary
There was an error loading the library "C:\Program Files\MyPath\MyFolder\MY_DLL.dll"
'C:\Program Files\MyPath\MyFolder\MY_DLL.dll' has different architecture than the host.
Caused by:
Error using loaddefinedlibrary
'C:\Program Files\MyPath\MyFolder\MY_DLL.dll' has different architecture than the host
Side note: my dll, lib, and header all have the same name

Melden Sie sich an, um zu kommentieren.

Kategorien

Gefragt:

am 10 Jul. 2017

Kommentiert:

am 25 Jul. 2017

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by