I'm trying to call a simple Matlab routine, from a Delphi XE 32bit application, which I have compiled into a shared C libray called Test.dll using the Matlab 2012b compiler.
The routine increments a number and returns the new value.
As I understand from the matlab documentation I first need to call mclInitializeApplication.
I've mapped this dll call as follows:
unit mclmcrWrapper;
interface
type
TAnsiArray = TArray<AnsiString>;
PAnsiArray = ^TAnsiArray;
function mclInitializeApplication(A: PAnsiArray; B: Integer): Boolean; cdecl; external 'mclmcr.dll' name '_mclInitializeApplication';
// Also tried, with same result:
// All attempts made with and without underscore give the same results.
// function mclInitializeApplication(A: PAnsiArray; B: Integer): Boolean; cdecl; external 'mclmcr.dll' name '_mclInitializeApplication';
// function mclInitializeApplication(A: THandle; B: Integer): Boolean; cdecl; external 'mclmcr.dll' name '_mclInitializeApplication';
implementation
initialization
mclInitializeApplication(nil, 0); //Initialize the matlab runtime
end.
According to ddlDepends the function is present in the dll.
When I execute my program I get the following error message:
---------------------------
MatlabTest.exe - Entry Point Not Found
---------------------------
The procedure entry point _mclInitializeApplication could not be located in the dynamic link library mclmcr.dll.
---------------------------
OK
---------------------------
All dll's are present in the same folder. If they are not I get an error that the dll itself cannot be found.
In itself this is also strange as the Matlab compiled runtime is installed on my system, and it is added to the windows path correctly.
Can anyone tell me what I'm doing wrong?
Thanks in advance.
So far as I know, that function is actually defined in mclbase.dll.
Once you resolve the linking, I suggest that you change the parameter list for your imported function. It's risky to pass Delphi managed types to a non-Delphi module. I would declare it like this:
type
PPAnsiChar = ^PAnsiChar;
function mclInitializeApplication(A: PPAnsiChar; B: Integer): Boolean; cdecl;
external 'mclbase.dll';
It turns out I had a couple of things to fix:
Install the MCR correctly.
Pass a PPAnsiChar instead of an array
Call "_proxy" functions in mclmcrrt8_0.dll, instead of the normal functions in the other dll files.
The method declaration is now as follows:
function DLLInit(A: PPAnsiChar; B: integer): Boolean; cdecl;
external 'mclmcrrt8_0.dll' name 'mclInitializeApplication_proxy';
in the unit I added the following code (yes, I'm not passing any parameters):
initialization
if not DLLInit(#MyString, 0) then
raise Exception.Create('Could not initialize Matlab library.');
I also made sure that this unit is the first to be loaded in the project, as the mclInitializeApplication needs to be called once and before all other matlab calls.
Related
I'm trying to call a function in a dll on a WinCE system.
this are the defines
type
TPREVIEW_CALLBACK = procedure ( pData: PByte; len: long; height: Integer; width: Integer; stride: Integer) of object; cdecl;
PPREVIEW_CALLBACK = ^TPREVIEW_CALLBACK;
function camRegisterPreviewCallback(PreviewCallbackProc: PPREVIEW_CALLBACK): Integer; cdecl; external 'CameraAPI.dll';
I made all functions global, this is the callback (still empty)
procedure PreviewCallback(pData: PByte; len: long; height: Integer; width: Integer; stride: Integer);
begin
end;
The call (also in a global function) is
CamRegisterPreviewCallback(PreviewCallback);
The error during compilation I get is
Error: Wrong number of parameters specified for call to "PreviewCallback"
As far as I understand it the parameter is a pointer so I don't understand what I'm doing wrong.
Can anyone help me on this?
Thanks in advance
Herman
When you write using the FPC dialect ({$MODE OBJFPC}) a function pointer must be explicitly specified using the # symbol.
Without this the compiler thinks that you want to call the function rather than to take its address.
So rewrite the last line as
CamRegisterPreviewCallback(#PreviewCallback);
By the way, as noted by someone in a comment, verify well your TPREVIEW_CALLBACK prototype. You declare its as of object but you implement it as a global function, which is an error. of object really means that the method has to be implemented in an class. The procedural variable of an object method is not the same as a procedural variable of a free function. In the first case there is an additional context pointer (the Self), so both are totally incompatible !
If the dll is written in C it's very likely that the of object is superfluous, but unfortunatly it's hard to say without the library API documentation.
How do I use Simulink.Bus.createMATLABStruct inside a function? I'm loading some bus definitions in the function's scope but createMATLABStruct doesn't see those. If I load the bus definitions in the global workspace then the function works.
Doesn't work:
function test()
load('someBuses.mat');
s = Simulink.Bus.createMATLABStruct('aBus');
end
Works:
load('someBuses.mat');
% ...
function test()
s = Simulink.Bus.createMATLABStruct('aBus');
end
Any ideas?
Simulink.Bus.createMATLABStruct accepts a 4th (undocumented) input -- open the file in the editor to see the 4th input -- which can either be 'base' (the default) or a Data Dictionary object.
The default is 'base', which is why the version you have that loads from the Base Workspace works.
Have a look at this link to find out about creating Data Dictionaries.
I have a very similar problem to the one described here: Make external functions accessible for other functions/modules in Fortran
I'm working with a DLL compiled from Fortran source code, using the Lahey/Fujitsu LF95 compiler and I'm trying to store a global reference to an external callback function (function pointer) so that it can be called at a later time from other functions in the Fortran DLL.
The scenario is something like this:
the host application invokes a subroutine (procedure) from the Fortran DLL and passes a reference to the callback function
a reference to the callback function should be stored as a global
later, the host application may call various functions from the Fortran DLL and these functions need to invoke the callback function, calling into the host application.
The problem is that the accepted answer from the question doesn't compile with the Lahey Fortran compiler. Apparently, there are quite some differences between the Intel compiler and the LF95 compiler.
I did get the callback reference to work fine in a single subroutine, like this:
subroutine testcallback(cbk)
dll_export :: testcallback ! Lahey LF95 extern declaration to export this function
character(len=*) :: text
interface
subroutine cbk (string, length)
character(len=*), intent (in) :: string
integer, intent (in) :: length
end subroutine cbk
end interface
text = "Hello World"
call cbk(text, len(text)) ! invoke the cbk callback; works very well
return
end
Invoking this function from the host application (C# in my case but that's inconsequential) works very well. I can pass in a function reference (delegatae in C#) and Fortran makes the call correctly and I get the expected results.
The issue is that I can't seem to be able to move the interface declaration outside of testcallback, and then subsequently call the cbk from a different Fortran function.
Here's an example of what I would want to accomplish:
subroutine setcallback(cbk)
dll_export :: setcallback ! Lahey LF95 extern declaration to export this function
interface
subroutine cbk (string, length)
character(len=*), intent (in) :: string
integer, intent (in) :: length
end subroutine cbk
end interface
! instead of calling cbk here, I'd like to save a reference to it and make it
! available to other functions..
return
end
subroutine testcallback()
dll_export :: testcallback ! Lahey LF95 extern declaration to export this function
character(len=*) :: text
text = "Hello World Again"
! somehow I want to be able to invoke the stored reference to cbk here
!
call cbk(text, len(text)) ! this obviously doesn't work like this
return
end
In closing I'd like to add that moving away from the LF95 compiler is not an option at this time. If anybody knows how to handle this I would very much appreciate it!
I am trying to connect a simulator to the MATLAB. The simulator program exposes a COM object interface.
I have connected to the COM object by the following command and can perform most of it methods:
h=actxserver(ProgID)
But some of its methods need passing of a Variant* type as output.
Here is the signature of one of the methods indicated by "invoke" method:
ReadOutputImage=Variant(Pointer) ReadOutputImage(handle, int32, int32, `ImageDataTypeConstants, Variant(Pointer))`
I have called this method with several syntax's, but none of them work:
a=uint8([0]) %means unsigned integer array with 1 member
h.ReadOutputImage(0,1,2,a) % 0 ,1 ,2 are contants pointing to the position, number of elements to read and size of elemnts while 2 shows Byte element (VT_UI2 COM type).
Other syntax's that I have tried and has no result are: using uint16, uint32, int8, int16, int32 for all of the followings:
logical types (like a=[false]),
cell arrays (like a={uint8([0])} )
empty cell array {}
empty array []
empty sring ''
I have used libpointer as well:
a=libpointer;
also a=libpointer('uint8Ptr',0)
also a=libpointer('bool',false)
also a=libpointer('bool',[0])
The problem is that I am not sure about the following items:
What is the similar type of " Variant(Pointer) " in MATLAB?
What is the method of passing a variable as output to a COM method in MATLAB?
Is it even possible to get a value from a COM object method result as a pointer in MATLAB?
To find how the data appears in other clients, I have imported the same dll file into Delphi and the signature of the type library for the above method is like this:
procedure ReadOutputImage(StartIndex: Integer; ElementsToRead: Integer;
DataType: ImageDataTypeConstants; var pData: OleVariant);
Yes Siemens has provided a guide for this com server (prosim) and based on such documentation I have connected and performed most of its methods. But the methods which read I/o data are not working. In documentation the method signature is specified as follows: (in VB)
STDMETHOD(CS7Prosim::ReadOutputImage)(long startindex,long elementstoread, imagedatatypeconstants DtaType, VARIANT* pData)
What about your application, was it working? Did it contains variant pointers as the returning argument? Did you have simillar methods in that application?
Thank you
I can help with #2 in your question. I just worked through this myself. Basically, any pass by reference to COM object you to access after it is modified, Matlab just spits back as an output.
[var1 a]=thisObject.DB.Execute(queryString,a)
See here
"The syntax shown here shows a server function being called by the MATLAB client. The function's return value is shown as retval. The function's output arguments (out1, out2, ...) follow this:
[retval out1 out2 ...] = handle.functionname(in1, in2, ...);
MATLAB makes use of the pass by reference capabilities in COM to implement this feature. Note that pass by reference is a COM feature. It is not available in MATLAB at this time."
I'm trying to write an ABL binding for the ØMQ C library, but am crashing the Procedure Editor for my zmq_init function binding. I wrote a binding for zmq_version without issue, so I assume it's not a .dll file problem. Anyway, the C function prototype looks like this:
void *zmq_init (int io_threads);
The ABL code I've written is as follows:
PROCEDURE zmq_init EXTERNAL "libzmq.dll" CDECL:
DEFINE INPUT PARAMETER num_threads AS LONG.
DEFINE RETURN PARAMETER context_ptr AS MEMPTR.
END PROCEDURE.
DEF VAR mContext AS MEMPTR NO-UNDO.
RUN zmq_init(INPUT 0, OUTPUT mContext).
This particular function initializes a "0mq context" (potential problem: it's a thread pool) and returns a pointer to it. Could the error be related to OpenEdge's non-threaded nature, even though I'm calling an external library and requesting 0 threads be allocated in the pool?
Running the code in Procedure Editor makes it crash with a Windows "Progress Client has stopped working" error with Exception code: C0000005 ACCESS_VIOLATION (full stack trace here, although I don't always get a stack trace with info in it).
I've never done Windows C programming, but it looks like what I'd call a Segmentation Fault if I were on Unix using gcc (accessing protected memory). Speaking of which, I'd in fact rather run this code on a Unix machine but apparently Progress only provides evaluation developer OE environments for Windows :(.
I've disabled DEP without success. Is ABL trying to dereference the pointer when it returns from the library or something? Surely there has to be a way to handle signatures with a return value of void* that get malloc'ed in the library call.
I've paged through OpenEdge Development: Programming Interfaces, Tom Bascom's UNIX Shared Libraries PowerPoint, and some other PowerPoint called OpenEdge in an LDAP World that has some code samples but don't see anything obvious that I'm missing.
I'm on OpenEdge 10.2B, Windows 7 64-bit, however using the 32-bit version of OpenEdge as that's my only option for evaluation software. Anyone got a license I could borrow for compiling/running this code on CentOS? :-)
You are missing PERSISTENT keyword when you are declaring your procedures.
Please try the following code:
zmq.p
&SCOPED DLLNAME 'libzmq.so'
PROCEDURE zmq_init EXTERNAL {&DLLNAME} CDECL PERSISTENT:
DEF INPUT PARAMETER NumThreads AS LONG.
DEF RETURN PARAMETER Context AS MEMPTR.
END PROCEDURE.
PROCEDURE zmq_term EXTERNAL {&DLLNAME} CDECL PERSISTENT:
DEF INPUT PARAMETER Context AS MEMPTR.
DEF RETURN PARAMETER ResultStatus AS LONG.
END PROCEDURE.
PROCEDURE zmq_version EXTERNAL {&DLLNAME} CDECL PERSISTENT:
DEF OUTPUT PARAMETER major AS LONG.
DEF OUTPUT PARAMETER minor AS LONG.
DEF OUTPUT PARAMETER patch AS LONG.
END PROCEDURE.
check_zmq.p
DEF VAR Zmq AS HANDLE NO-UNDO.
DEF VAR MajorVersion AS INT NO-UNDO.
DEF VAR MinorVersion AS INT NO-UNDO.
DEF VAR PatchVersion AS INT NO-UNDO.
DEF VAR CallStatus AS INT NO-UNDO.
DEF VAR ZmqContext AS MEMPTR NO-UNDO.
RUN zmq.p PERSISTENT SET Zmq.
RUN zmq_version IN Zmq ( OUTPUT MajorVersion, OUTPUT MinorVersion, OUTPUT PatchVersion ).
MESSAGE MajorVersion MinorVersion PatchVersion.
RUN zmq_init IN Zmq ( 1, OUTPUT ZmqContext ).
RUN zmq_term IN Zmq ( ZmqContext, OUTPUT CallStatus ).
MESSAGE CallStatus.
FINALLY:
IF VALID-HANDLE(Zmq) THEN
DELETE PROCEDURE Zmq.
END FINALLY.
Could the error be related to OpenEdge's non-threaded nature, even though I'm calling an >external library and requesting 0 threads be allocated in the pool?
I ran into the same problem several times (Progress Client has stopped working) while i was working on some c# methods (called via clr bridge) in which I used threads.
Hiding the threads from progress by using some c# library classes(AsyncOperation,AsyncCallback) solved the problem, but most attempts caused the progress runtime to stop.
Related to .net the progress help states "You cannot use System.Threading.Thread, or any derived class — ABL is single-threaded."
I know that calling c# methods via clr bridge is completely different from invoking c libraries but maybe our problems are caused by the single threaded nature of OpenEdge.
I grabbed your code from github and changed the MEMPTR variables to INT64. This allowed it to run without crashing (10.2b05 32-bit on 64-bit Windows 7). Since the memory is being handled by zeromq, I think this is a safe way to handle the issue.