matlab , MEX crash debugging ( MATLAB with PARDOX DATABASE)

we operate a DLL written in PASCAL / DELPHI exchanging simple datatypes between  a Delphi application and a Matlab code.
One program version has been used very stable for a longer time periode. Now we changed the Matlab enviroment, the computer hardware ....
.... we suffer an random matlab full crash while trying to access the Delphi / dll .

we operate a Delphi Hostapplication for that DLL without any problem, also a not complete test of the DLL from Visual C++  seem to be functional.

We believe Matlab, MEX, Matlab RUNTIME are buggy,   need help to continue the debugging. Any proposal ?
LVL 8
BdLmAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

BdLmAuthor Commented:
the reason :  

compile our dll with D 7   compiler -> everything is pass

compile with D 2010 compiler  ->  strings from matlab are corrupted


what is equivalent to char*  in Delphi 2010, PChar does not seem to be that solution any longer ....
0
BdLmAuthor Commented:
what I found out in the meantime :


PChar in D7 has to be replaces by PAnsiCHar in D2010 to match dataexchange with matlab , should I made a *.zip or a project on Source forge with all the code examples for further discussion ?
0
Emmanuel PASQUIERFreelance Project ManagerCommented:
You are correct, Delphi 2009 introduced a major change with Unicode strings.

All Char, Strings, and pointers on those do no longer translate to ANSI (ASCII) chars & strings but unicode (2 bytes per char).

So, when Delphi procedure receive a PChar parameter from a "classic" dll where strings are supposed to be zero terminated ANSI strings (C strings), Delphi will try to convert this thinking it is a zero terminated Unicode string. So it will wait for a null double byte, and until it reach one it will convert 2 chars into one Unicode. At the best, result will be garbage full of chineese characters mostly. At the worst, yet not the most unlikely, it will not reach a double zero until it hit a protected memory zone and crash the application.

Know that the explicit Unicode type is WideChar / WideString , for all Delphi versions.
So, Prior Delphi 2009 : String => ANSIString
D2009 and after : String => WideString

I all versions, use of ANSIString and WideString remove all ambiguities and you can/should use those whenever you MUST be sure you are talking about ANSI or Unicode strings, and not let Delphi decide for you.

Solution :
a) make a replace for all Char into ANSIChar, String to ANSIString, and pChar to pANSIChar.
But doing this can be a problem, if done on a large scale. Delphi will rely on Unicode for all its API, components etc... So each time you pass ANSIString to functions needing String, an implicit conversion will occur. Same goes for other types pair, and convertions the other way. You will end up with massive loss of performance.

b) do it smartly, only on the interface procedures that need data exchange with external applications/dll. You use ANSIChar and ANSIStrings on those API procedures, which convert the parameters to unicode parameters, call a similar procedure using unicode parameters and eventually convert back some output parameters or string function results after that unicode procedure and before returning to the caller.
Ex :

Your code before (I will try to imagine a single function with the most possible type of cases) :

// this function will be exported
procedure SomeProcedure(ParamIn:String; ParamOut: pChar; MaxOutSize:Integer );
begin
 // do something
end;

Now :

// keep the same function name but with explicit ANSI, to conserve the same external signature (C compatible)
procedure SomeProcedure(ParamIn:ANSIString; ParamOut: pANSIChar;  MaxOutSize:Integer);
Var
 ParamInW:WideString; // I could have said String, but the use of WideString is more explicit for the occasional code reader
 ParamOutW:WideString;
 ParamOutA:ANSIString;
begin
 ParamInW:=ParamIn; // explicit conversion
 // ParamOut : no conversion in entry, simply set length of a temp variable
 SetLength(ParamOutW, 2*MaxOutSize);
 SomeProcedureW( ParamInW , pWideChar(ParamOutW), MaxOutSize ); // keep MaxOutSize if the proc implementation think "size" as the nb of characters, or *2 if it is the size in bytes... Just a matter of choice
 // now convert back the result to ANSI 
 ParamOutA:=ParamOutW; // Delphi will translate as best it can the unicode string to the ANSI string
 StrLCopy( ParamOut , pANSIChar(ParamOutA), MaxOutSize ); // Copy the converted ANSI data back to its intended buffer
end;

// This function has the same syntaxic signature as before, but IT IS different (String=WideString now)
procedure SomeProcedureW(ParamIn:String; ParamOut: pChar; MaxOutSize:Integer );
begin
 // do something, same code as before
end;

Open in new window

0
Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

Emmanuel PASQUIERFreelance Project ManagerCommented:
just one last note :
you would have had a lot more answers and sooner by adding the "Delphi Programming" zone in your question
0
BdLmAuthor Commented:
I changed several Delpi DLL functions to

function  AnyCodeOne ( aValue : PAnsiChar)  or
function  AnyCodeTwo ( aValue : Integer (Real))  : PAnsiChar)

both solutions seem to work fine and stable . If possible I want to abvoid MaxOut parameter in the function call. The total dll has about 30 functions , the only function which fails is


   ///  Version Constants
   DLLVer_Major                 = 6;
   ///  Version Constants
   DLLVer_Minor                 = 6;
   ///  Version Constants
   DLLVer_Copyright             = 'Copyright (C) by Me ';

   DLLName                      = 'delphi2matlab.dll';




///  tiny msg box with informations on the *.dll file
function DllGetVersion : PAnsiChar ;  stdcall;
begin
     result :=  PAnsiChar( AnsiString( DLLName +' Version ' + IntToStr(DLLVer_Major) + ':' + IntToStr(DLLVer_Minor) )) ;
end;


Final remark :

Using PChar indead of PAnsiCjar matlab crashes completly I nnned to restart my computer,
can't shut down matlab with the TASK manager any longer !!!!!!
0
Emmanuel PASQUIERFreelance Project ManagerCommented:
that is because you are building your response in the stack and returning a pointer on it, this memory zone will be overrun pretty soon with other data.

If you cannot avoid that dynamic building of the version string, then build it in a global (ANSI) string variable instead :

Var
 VersionStr:ANSIString;

function DllGetVersion : PAnsiChar ;  stdcall;
begin
 VersionStr:=Format('Version %d:%d', [ DLLVer_Major , DLLVer_Minor ] );
 result :=  PAnsiChar( VersionStr ) ;
end;
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
BdLmAuthor Commented:
Thanks for your help finding the solution !!!!!!!!!  it  works !


The function DLLgetVersion has been functional at DELPHI 7 with  Pchar / String datatype - shouldn#t  this bug have been there also???  

0
Emmanuel PASQUIERFreelance Project ManagerCommented:
it depends on how smart Delphi compiler is. I think it is pretty smart, so that it could understand that this :
 DLLName +' Version ' + IntToStr(DLLVer_Major) + ':' + IntToStr(DLLVer_Minor)

is a string constant that it can evaluate at compile time, so the pChar pointer will be on a code const mem zone, not in the stack.

But calling AnsiString( aConstWideString ) cannot be evaluated at compile time because of code page that can be different from one system to the other, so only at runtime
0
Emmanuel PASQUIERFreelance Project ManagerCommented:
ah, if that can be arranged, can you add 'Delphi Programming' to the zones related to this question ?
0
Emmanuel PASQUIERFreelance Project ManagerCommented:
hope others also will  find that solution ...
the sad thing is that they won't, it is not in the good zone

Still, I'm glad it helped you
0
yuk99Commented:
BdLM:
I followed this question and I'd like to ask you for a favor to EE community.

I'm not a Delphi programmer but there were recently many questions in MATLAB zone on how to integrate Delphi and MATLAB.  And I didn't see a good solution neither on EE or anywhere. Since you were successful (even using two Delphi version) it would be great if you could write an article on this topic with some code examples. I believe others would appreciate it a lot.

Thanks in advance.
0
BdLmAuthor Commented:
@yuk99:  OK will do that, need    ~  1 weel for that , where to send the article ?
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Programming Languages-Other

From novice to tech pro — start learning today.