Matlab 2016 backward compatibility issue with loadlibrary

Dear Matlab Aficionados,
I am hoping someone can help me. I am trying to get Matlab 2016a loadlibrary() to accept loading a DLL that has an extern C declared header file with a forward declared struct inside. The same exact code works fin in older versions of Matlab like 2015a, but something changed in the 2016 version. I cannot use an #include statement inside the extern C declaration as a workaround by including the header file with the full definition of the struct in question because that full definition contains C++ classes. Is there anything I can do that will fix this issue? Can the older behavior of permitting forward declarations be reinstated in the future? It sure would save me a lot of code modification if I can find a solution.
This is what I mean:
inside "dll.h":
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
int a;
double *data;
} struct1;
struct struct2;
}
inside "dll_private.h"
#include "classes.h"
struct struct2
{
className objectName;
};
UPDATE: I just reinstalled Matlab 2015b to see if I can reproduce the issue. The issue exists there as well. I am thinking this error is compiler-specific. When I reinstalled Matlab, I removed a lot of previous Matlab-related things. I also removed the old Visual Studio 2012 and replaced with Visual Studio 2015. The error I get is this:
Error using loadlibrary
Building DLL_thunk_pcwin64 failed. Compiler output is:
cl -I"C:\Temp\include" /Zp8 /W3 /nologo -I"C:\Temp" -I"C:\Temp\inc"
"DLL_thunk_pcwin64.c" -LD -Fe"DLL_thunk_pcwin64.dll" DLL_thunk_pcwin64.c
C:\Temp\inc\DLL.h(727): error C2143: syntax error: missing '{' before '*'
C:\Temp\inc\DLL.h(733): error C2081: 'ForwardDeclaredStructName': name in formal parameter list illegal
My understanding is to list the compiler that Matlab can see, do "mex -setup":
mex -setup
MEX configured to use 'Microsoft Visual C++ 2015 Professional (C)' for C language compilation.
What can I do to get the original functionality that I used to have of being able to use loadlibrary with a forward declared struct pointer? Do I need to install Visual Studio 2012 and then change the default compiler to use it using "mex -setup"?
Update: I also tried 2015b (64bit) with Visual Studio 2012 DLL compiled in 64-bit (I used mex -setup to change to the VS2012 compiler after installing VS2012). I also recompiled the DLL with VS2012. The issue still persists. I am wondering if this is a 32 vs. 64-bit issue as Phil hinted at below.
Kind regards, Kris Walker

 Réponse acceptée

Your header file is c++ code and thunk files are c there is no way this could have worked in 64 bit MATLAB. Was your previous MATLAB 32 bit? If so then you need to rebuild all libraries for 64 bit and fix the header so it will compile as c code. That usually evolves wrapping extern "C" { with an ifdef:
#ifdef __cplusplus
extern "C" {
#endif
... /* extern c code */
#ifdef __cplusplus
}
#endif

6 commentaires

Hi Philip. Thanks for the quick reply!
I just crossed the 32-bit to 64-bit transition recently. So it may have been that it only worked in 32-bit version of Matlab/VS before. I can try installing a 32-bit version of Matlab as a next step. However, please know that the public DLL.h file is already wrapped in extern C in the way you posted. I was being lazy. I am updating my post now to show this.
The DLL.h does not #include the private.h file that has the forward declared struct's member definition, part of which is defining class objects that Matlab would not know how to handle. If you have any other ideas, please feel free to share.
I do still suspect the problem surfaced due to switching to 64 bit MATLAB. I can't tell from the error message the cause of the compile error near line 727 of DLL.h an excerpt from the file would help or trim down to just problem code I think the code you posted would work. One way to debug the problem is to create a dummy main.c or mex file and add your loadlibrary include to the top and try compiling which should succeed.
Hi Phil,
Line 727 looks like this:
TEST_API Struct2 * AllocateMemoryStruct2(Struct1 *);
Line 733 looks like:
TEST_API int MainFunction(Struct1 *, Struct2 *);
I am currently installing 32-bit Matlab 2015b. I'll see if that makes a difference. If it doesn't, I'll explore loadlibrary in a main.c.
UPDATE: I have been able to reproduce the difference. Installing 32-bit Matlab 2015b and recompiling the DLL in 32-bit solves the problem. In that case, loadlibrary loads the DLL.h correctly with the forward declared struct. I confirmed this works for both VS2012 and VS2015 compilers when using mex -setup to change between both. It appears there is something about the 64-bit nature of Matlab or the VS compilers that do not permit the forward declarations. If there is any other ideas someone has to debug that will enable me to work in 64-bit, please let me know.
Update 2: I created a main.c function and used Windows.h LoadLibrary to load the DLL. Then I printed out the error code after the load. I tested the error code to make sure it was reliable, and it was giving me error = 193 and 126 when I purposefully broke it. But when I ran the same loadlibrary command I was giving 64-bit Matlab, it was returning a 0 error code after pausing for about a second. Interestingly, when I compile and test in 32-bit mode, it takes about twice as long to load the DLL and report the 0 error code. Anyway, it does report no error either in 32-bit or 64-bit mode when using Windows.h LoadLibrary. Any ideas why Matlab-64's loadlibrary is behaving differently?
Thanks again, Kris
Your function deceleration is legal in C++ but not c did you create a c or cpp test program? To use a struct in a c deceleration you need the struct keyword:
struct struct2* AllocateMemoryStruct2(struct1 *);
struct1 does not need struct because it is a typedef. An alternitive option is to forward declare struc2 with:
struct struct2_;
typedef struct struct2_ struct2;
Hi Phil,
I'm back in business! Thank you!!
Just for the benefit of others, regarding the legality, I compiled in Visual Studio C++ mode using the extern C conditional logic around it as mentioned above. It has always worked in the past in 32-bit Matlab form. But it does not work in 64-bit Matlab. So I expect it was always illegal, but Matlab-32 was more forgiving than Matlab-64. Adding "struct" prefix to struct2* in the public definitions fixes the issue and permits me to once again forward declare struct2.
I also tried the 2nd solution, but if I do this, Visual Studio complains about a redefinition of struct2 in the private *.h file where I'm providing the struct2 member information.
Thanks again, Kris
32 bit MATLAB does not need thunk files and therefor does not actualy compile any code with the header used for loadlibrary. As a result of this it can be much more forgiving about the code in the header file.

Connectez-vous pour commenter.

Plus de réponses (0)

Community Treasure Hunt

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

Start Hunting!

Translated by