Solved

Interfacing with matlab dlls from Delphi

Posted on 2010-11-18
7
1,835 Views
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)
Output=Input+1;

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:
Input:=1;
MatlabFunc(1,Output,Input);

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.
0
Comment
Question by:PaulC76
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
7 Comments
 
LVL 25

Expert Comment

by:epasquier
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

0
 
LVL 21

Expert Comment

by:developmentguru
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.
0
 

Author Comment

by:PaulC76
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
x=2;
x=x+1;

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:

#if defined(ARRAY_ACCESS_INLINING) && !defined(MATLAB_COMPILER_GENERATED_CODE)
/*
 * 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;
};
#endif /* ARRAY_ACCESS_INLINING */

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.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:PaulC76
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:

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

Open in new window

Implementation:
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.
0
 
LVL 25

Expert Comment

by:epasquier
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

0
 

Author Comment

by:PaulC76
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.
0
 
LVL 25

Accepted Solution

by:
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
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
numbers ascending pyramid 101 264
What language/protocol is the Angular Chat? 2 110
how to change, disabled button color FMX ? 1 64
Delphi, TImage, Png 2 54
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Having just graduated from college and entered the workforce, I don’t find myself always using the tools and programs I grew accustomed to over the past four years. However, there is one program I continually find myself reverting back to…R.   So …
The viewer will learn how to implement Singleton Design Pattern in Java.
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.

739 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