Interfacing with matlab dlls from Delphi

Posted on 2010-11-18
Last Modified: 2016-03-02
I am trying to use functions written in Matlab from Delphi. The test function is very simple, it just adds one to an input variable as follows:

function [Output] = AddOne(Input)

I've managed to compile it ok and access the dll from delphi, but I get an access violation at the line where I try to use the function.

l define the function in Delphi as follows:

In the interface:

function MatlabFunc(NRetValues: Integer;var Output: Variant;var Input: Variant): Variant; cdecl;

In the implementation:

function MatlabFunc(NRetValues: Integer;var Output: Variant;var Input: Variant): Variant; cdecl; external 'AddOne.dll' name '_mlxAddOne';

Then call it:

I've installed all the relevant matlab runtime libraries and everything seems to work ok, I think it's just a matter of figuring out the correct calling convention. Or do I have to use mclInitializeApplication or something? It does appear from web searches that people have had similar problems and that some people have managed to solve it, but no-one explains quite how.
Question by:PaulC76
  • 3
  • 3
LVL 25

Expert Comment

ID: 34169621
the calling convention is most probably stdcall;

for the parameters types translation, it would be useful to have C headers (.H files), probably generated when you compile your function.
I doubt very much that those parameters are Variant.

I think also that you have to call the initialize function for the lib, and call the Terminate when done.

something like
function MatlabFunc(NRetValues: Integer;var Output: Variant;var Input: Variant): Variant; stdcall; external 'AddOne.dll' name '_mlxAddOne';

procedure AddOneInitialize; stdcall; external 'AddOne.dll'  name '_MatlabFuncInitialize';

procedure AddOneTerminate; stdcall; external 'AddOne.dll'  name '_MatlabFuncInitialize';

Open in new window

LVL 21

Expert Comment

ID: 34170566
The MatLab compiler generates both the dll and a header filer.  Can you post the header file?  Many experts are good at translating a C / C++ header into the correct Delphi calling conventions.  From what I have been able to tell MatLab generates CDecl calling conventions.

Author Comment

ID: 34182881
I have since tried calling the mclInitializeApplication first and then using a function which has no parameters and still get the same error. In the interface I now have:
function InitialiseMatlab(): Boolean; cdecl;
function NoParam(): Boolean; cdecl;

Open in new window

and in the implementation:

  function InitialiseMatlab(Options: Variant; Count: Word): Boolean; cdecl; external 'NoParam.dll' name '_NoParamInitialize';
function NoParam(): Boolean; cdecl; external 'NoParam.dll' name '_mlfNoParam';

Open in new window

The function in matlab is as follows:

function NoParam

Open in new window

The InitialiseMatlab function executes ok, but returns false. An access violation then occurs when NoParam tries to execute. Matlab generates a header file and c code, which are attached.

 NoParam.h NoParam.c

The header file has the relevant interfaces to the function:

extern LIB_NoParam_C_API 
bool MW_CALL_CONV NoParamInitializeWithHandlers(mclOutputHandlerFcn error_handler,
                                                mclOutputHandlerFcn print_handler);

extern LIB_NoParam_C_API 
bool MW_CALL_CONV NoParamInitialize(void);

extern LIB_NoParam_C_API 
void MW_CALL_CONV NoParamTerminate(void);

extern LIB_NoParam_C_API 
bool MW_CALL_CONV mlxNoParam(int nlhs, mxArray *plhs[],
                             int nrhs, mxArray *prhs[]);

extern LIB_NoParam_C_API bool MW_CALL_CONV mlfNoParam();

Open in new window

Any parameters if needed are mxArray types, which is partially defined in the header file Matrix.h as follows:

 * This modified version of the mxArray structure is needed to support
 * the ARRAY_ACCESS_INLINING macros.  NOTE: The elements in this structure
 * should not be accessed directly.  Inlined MEX-files are NOT guaranteed
 * to be portable from one release of MATLAB to another.

struct mxArray_tag {
    void    *reserved;
    int      reserved1[2];
    void    *reserved2;
    int      number_of_dims;
    unsigned int reserved3;
    struct {
        unsigned int    scalar_flag : 1;
	unsigned int	flag1 : 1; 
        unsigned int    flag2 : 1;
        unsigned int    flag3 : 1;
        unsigned int    flag4 : 1;
        unsigned int    flag5 : 1;
        unsigned int    flag6 : 1;
        unsigned int    flag7 : 1;
        unsigned int    private_data_flag : 1;
        unsigned int    flag8 : 1;
        unsigned int    flag9 : 1;
        unsigned int    flag10 : 1;
        unsigned int    flag11 : 4;
        unsigned int    flag12 : 8;
        unsigned int    flag13 : 8;
    }   flags;
    unsigned int reserved4[2];
    union {
        struct {
            void  *pdata;
            void  *pimag_data;
            void  *reserved5;
            int    reserved6[3];
        }   number_array;
    }   data;

Open in new window

Converting that to Delphi is the point where I give up I think, I've spent more time than I have for this already.
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!


Author Comment

ID: 34186868
My previous comment was a bit confusing. In the example I posted I didn't use the global mclInitializeApplication, but the local initialisation function NoParamInitialize. I have since tried with mclInitializeApplication as follows:

TCharPointer = ^Char;
TCharPointerPointer =^TCharPointer;
function InitialiseMatlab(const Options:  TCharPointerPointer; Count: Word): Boolean; cdecl; 

Open in new window

function InitialiseMatlab(const Options:  TCharPointerPointer; Count: Word): Boolean; cdecl; external 'mclmcrrt76.dll' name 'mclInitializeApplication';

Open in new window

The C header as given in the Matlab help is:
bool mclInitializeApplication(const char **options, int count);

Open in new window

In the example in the Matlab help "mclInitializeApplication(NULL,0);" is given as an example of usage, I've tried "InitialiseMatlab(nil,0);" and passing pointers to pointers to #0, but always get a return value of False.
LVL 25

Expert Comment

ID: 34187031
why do you have thie ?
function InitialiseMatlab(Options: Variant; Count: Word): Boolean; cdecl; external 'NoParam.dll' name '_NoParamInitialize';

shouldn't you call this :

function InitialiseMatlab: Boolean; cdecl; external 'NoParam.dll' name '_NoParamInitialize';

if InitialiseMatlab Then ShowMessage('Good') Else Raise Exception.Create('Could not initialize MathLab Dll');

Open in new window

then : TCharPointer = ^Char;
that type already exists, that's PChar. But I recommend using PAnsiChar, because if you have Delphi >=2009 then Char = WideChar (unicode), so for C dll you have to use ANSIChar explicitly. And Count is not Word (2 bytes) but Integer (or Cardinal)

function InitialiseMatlabOptions(const Options:  ^PANSIChar; Count: Integer ): Boolean; cdecl; external 'NoParam.dll' name 'mclInitializeApplication';

Open in new window


Author Comment

ID: 34187191
Very sorry, the function was InitialiseMatlab was defined as you have it in your first code segment, it was copied from code I was in the middle of changing to use the mclInitialize function instead of NoParamInitialize. I also had originally defined Count as an Integer, but changed it to Word as part of my desperate and lazy trial and error approach. Also Delphi doesn't allow you to define pointers as function parameters in the function prototype (e.g.^PANSIChar), you have to define them as types first.

Anyway, I've since done as you kindly suggested and it still returns false. Thanks very much for your help with this, but please don't waste any more time on it, as I'm not able to spend too long on it myself now and I don't want to trouble anyone else with it too much.
LVL 25

Accepted Solution

epasquier earned 250 total points
ID: 34187324
Ok, I'm about sure that those Delphi declarations are good, compared to the C headers. So, since it returns False, and don't raise exceptions of any kind, we have to suppose that the call is working, but for a reason it cannot initialize MathLab... Maybe some wrong parameter in you MathLab environment

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
format the code in java 6 72
Delphi XE10 Round Image 2 50
Specific format 21 142
QRReport  TQrmemo vertical stretching 1 37
Navigation is an important part of web design from a usability perspective. But it is often a pain when it comes to a developer’s perspective. By navigation, it often means menuing. This is less theory and more practical of how to get a specific gro…
How to remove superseded packages in windows w60 or w61 installation media (.wim) or online system to prevent unnecessary space. w60 means Windows Vista or Windows Server 2008. w61 means Windows 7 or Windows Server 2008 R2. There are various …
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now