MATLAB Answers

0

How do I wrap MATLAB Compiler R2014a created C DLLs to create another DLL?

I am trying to use a MATLAB Compiler R2014a created a C shared DLL file in my application. However, my application loads DLLs as a plug-in and cannot be instructed to call the required MCR initialization steps and data conversion steps required.

Tags

No tags entered yet.

Products


Release

R2014a

3 Answers

Answer by MathWorks Support Team on 18 Sep 2019 at 4:00
Edited by MathWorks Support Team on 18 Sep 2019 at 12:39
 Accepted Answer

Note that the following information is valid for MATLAB release R2014a and newer. For previous releases see:
http://www.mathworks.com/matlabcentral/answers/94715-how-do-i-wrap-matlab-compiler-4-8-r2008a-created-c-dlls-to-create-another-dll
MATLAB Compiler R2014a generated DLLs do not have the ability to enable functions calls without first initializing the MCR and the library. Addtionally, they deal primarily with mxArray data types.
To work around this, the MATLAB DLL can be wrapped by an intermediate level of code which does the following:
1. Initialize the MCR and load the MATLAB DLL (the first time it is called).
2. Convert data formats of the driver into MATLAB data (mxArray).
3. Call the MATLAB functions from the MATLAB DLL.
4. Convert MATLAB data back into data type formats that the driver can understand.
The attached file shows an example using C code.
This example was tested using MS Visual C++ 2010 Professional Edition.
Level 1 : MATLAB code
----------------------
level1.m contains the MATLAB code which implements the functionality required from the MATLAB DLL. level1.m contains a MATLAB function which takes a 2D matrix and a string. The function displays the string using a dialogue box and returns the input matrix multiplied by 2.
A DLL is compiled from this MATLAB code using the following command:
NOTE: Ensure that a level1.dll from a previous run does not exist on the path before executing the following.
mcc -v -B csharedlib:level1 level1.m
This step creates level1.dll, level1.lib and level1.h among others.
Level 2 : Wrapper code
-----------------------------
The wrapper code level2.c handles the four tasks mentioned above. When working with MSVC++, this is compiled to create level2.dll using the following command:
mbuild -v level2.c level1.lib LINKFLAGS="$LINKFLAGS /DLL /DEF:level2.def" LDEXT=".dll" CMDLINE250="mt -outputresource:$EXE';'2 -manifest $MANIFEST"
level2.def is a plain text DEF-file listing the name of the library and the functions in level2.c which need to be exported (visible) in the generated level2.dll file. Please note that level2.dll is dependent on level1.dll
If working with MinGW64, compile the DLL using:
mbuild -v -g level2.c level1.lib LDFLAGS="-shared $LDFLAGS" LDEXT=".dll"
Note that MinGW64 does not require a DEF-file.
Level 3 : Driver code
--------------------------
This code is indicative of the final driver code. No initialization steps are required and the functions can be called with C data types. This driver code, level3.c, is compiled using the following command:
mbuild -v level3.c
Note that the final execution of level3.exe requires level2.dll and level1.dll to be available in the same directory as this executable or somewhere else on the system path.

  2 Comments

Hi, I have done the above successfully for the following case involving 3 steps. step 1: Call the matlab dll, which reads in some foreground images from disc. Concatenate and send back images as output, via the wrapper, to the calling C program. step 2: Call the matlab dll, which reads in some background images from disc. Concatenate and send back images as output, via the wrapper, to the calling C program. step 3: Pass in the above concatenated foreground and background images into the matlab dll and perform some image processing. Send back, via the wrapper, a set of success codes to the calling C program.
Where I am having a problem is when I try to call the dll from within LabView. So to be clear, I am using Labview to acquire (currently reading from disc) the 2 sets of images, i.e. steps 1 and 2 above. I then call the matlab dll (via the wrapper) with the s concatenated images as inputs. As part of this call I need to specify the size of the mxCreateDoubleArray, which I specify as 1 x 8601600 sizeof(double). I seem to have a problem when this size is more than 1 x 1000000.
Does anyone know of any restrictions in terms of the size of the data array that I can pass into a matlab dll in this way?
Thanks, Garry
You can use mxCreateDoubleScalar to create a scalar double mxArray. The function is unsuccessful when there is not enough free heap space to create the mxArray.

Sign in to comment.


Answer by Rick
on 9 May 2014

Hi, I am trying to accomplish something similar, and I followed the steps in wrapperCDllR2014a.zip but I would like to use some functions from the optimization toolbox. Is this possible? How can I link in the toolbox? I get access violations based on
Undefined function 'fmincon' for input arguments of type 'function_handle'.
Undefined function 'optimoptions' for input arguments of type 'char'.
Thank you in advance

  1 Comment

Hey Rick,
Optimization toolbox functions are deployable, and should be picked up automatically when you deploy your MATLAB code.
You might be running into this bug: EBR 1059029

Sign in to comment.


Answer by DanTun
on 29 Aug 2016
Edited by DanTun
on 29 Aug 2016

Hi, I am also trying to use this method, I have followed the steps to get the level2.dll and running level3.exe returns as expected. However, when I try to call from labview the dll returns only a single number (~4E-315) no matter what the input matrix is. The input message is displayed and labview is not returning any error from the library call function, but I just can't get it to return the data. Please help. If anyone could post an example vi that would be great. I'm using matlab 2016a with the appropriate MCR installed, labview 15 64bit and visual studio 2015. I've attached the files I am working with below.

  2 Comments

I found a way to make it work, though it may not be the most elegant due to my lack of experience - would be happy to see a better solution. The problem was that level2.dll was returning a pointer address (to the memory holding the array) rather than the array itself, and labview couldn't figure it out (or I couldn't figure out how to tell it to). Hence the single strange number (the result of reading a 64-bit Integer as 8-byte Double). The solution involves taking the pointer address and dereferencing to get the array using labview's GetValueByPointer VI. Solution attached below in case it helps anyone.
Hello DanTun, If you still need assistance with this issue, you can contact MathWorks Technical Support.

Sign in to comment.