I have a piece of equipment that I would like to control from within Matlab on WinXP32. Its APIs are packaged in a DLL with an associated C header.
The device's API functions rely on a hardware descriptor, which is accessed by its Win32 handle and can only be directly manipulated by the API functions. From the "foo.h" header provided by the manufacturer:
typedef HANDLE BAR
#ifdef _DLL_EXPORT
#define _DLL_API __declspec(dllexport)
#else
#define _DLL_API __declspec(dllimport)
#endif
This handle is then used by the API functions, whose C signatures are of the form:
FOO_RETURN Device_Init(BAR *pbar, DWORD parameter1, ....)
Moving to Matlab, I load the library:
loadlibrary('foo','foo.h');
and the API functions are now available in Matlab. In libfunctionsview, their signatures look like:
Name Arguments
Device_Init (voidPtr, uint32, ....)
and the "foo.m" function created by loadlibrary describes them as:
fcns.name{fcnNum}='Device_Init'; fcns.calltype{fcnNum}='stdcall'; fcns.LHS{fcnNum}="uint32'; fcns.RHS{fcnNum}={'errorPtr, 'uint32', ...)
My problem is this handle "BAR". None of the following are accepted:
pbar = libpointer('BAR'); % Type was not found
pbar = libstruct('BAR'); % Undefined function or variable 'lib.BAR'
pbar = libpointer; % Segfaults when passed to DLL
Is there a way to create and manage this handle "BAR" in Matlab so that it can be used in Matlab calls to calllib('foo','command',pbar,....) ?
You can try this code to create the MATLAB pointers:
pbar = libpointer('voidPtr',[ uint8('some string') 0])
pparameter1 = libpointer('uint32',0)
and to call your DLL function use the following command:
calllib('foo','Device_Init',pbar,pparameter1,...)
Related
I meet a problem in the s function builder, I have to use a temp structure variable to transport the inputs to the extended C function.
Background: csolve function is a quadratic programming solver generated by CVXGEN for my QP problem, and I have tested the function in level-2 matlab s-fun. Now I want to use s function builder to genetate the TLC file that support the embedded code generate.
My Problem:
1) I have to use a temp structure variable 'params' to the inputs to csolve function in the outputs panel, could you please help me to solve this problem?
2) I find that in cvxgen folder contains a header file contains 'tic' and 'toc' function, how to use these functions in s function builder?
params.Aeq=Aeq;
params.beq=beq;
params.Aineq=Aineq;
params.bineq=bineq;
params.Smat=Smat;
params.Wmat=Wmat;
params.alpha=alpha;
[vars, status] = csolve(params)
y0=vars.x;
converge=status.converge;
for the attached files please see here
First some background information that you should know:
Matlab and C work completely differently and use different kinds of data types. To call C code from Matlab, so called "mex-functions" are generated. Matlab uses a special data type named mxArray to exchange data between Matlab and these "mex-functions", which are written in C.
In the C program an element (for example a variable) of the type mxArray represents a Matlab value of any data type. Matlab provides some functions (like mxGetData()) to access the actual data of the Matlab data element from the C function: There is some function for checking if the mxArray represents a floating-point value or a string. Another function allows you to convert the value from mxArray to double if the element has a floating-point value.
[vars, status] = csolve(params)
This means you want to call a "mex-function" from an "S-function".
Theoretically, this is possible but it is not as easy as you think:
First of all, the entry point of both types of functions is named mexFunction() in the C code. This means you cannot simply combine the C codes of both functions because in this case you would have two functions with the same name (mexFunction) in your S-function.
You might call the function mexCallMATLAB; however Mathworks writes that this function should not be called from S-functions.
The other possibility would be loading the mex-function using DLL functions (in Windows: LoadLibrary, GetProcAddress, FreeLibrary) and call the function mexFunction() of the mex-function using a function pointer.
However, in this case you have to convert all C data types to mxArray data and the data returned from the mex-function must be converted back ...
... a TLC file that is needed in ... embedded coder
The functions that access data of the mxArray type are only available when Matlab is running.
If you generate code that shall be executable outside Matlab, you cannot use mxArray and therefore you cannot call mex-functions.
The file csolve.c defines four structure variables:
Vars vars;
Params params;
Workspace work;
Settings settings;
And what the file actually does is the following:
Read the structure params (mxArray data type), convert these content to C data types and write the data into the four structure variables above
Call the following code:
steps = solve();
for (i = 0; i < extra_solves; i++)
solve();
The function solve() is defined in the other .c files in the project.
Take the values from the four structure variables and the value step returned by solve() and convert the data to mxArray.
Return the result as [vars, status]
You can define the four variables in your S-function code, fill these structures the same way the file csolve.c does it, call the solve() function as it is shown above and read the data of vars and status directly from the four variables.
You remove csolve.c from your project and add the other .c files of your mex-function to the S-function.
I'm trying to generate C code for a simple function Matlab funciton:
function[] = myfunc()
%#codegen
fprintf('Executing myfun\n');
fid = fopen('file_created_by_myfun.txt','w');
fwrite(fid,'This is written by myfun upon execution');
fclose(fid);
end
However, in the generated code a variable type boolean_T is used but not declared anywhere. It seems to me that no header with its declaration was included.
The script to generate the code is:
config_obj = coder.config('exe');
config_obj.GenCodeOnly = 'on';
codegen -config config_obj myfun
By calling make with a custom makefile, I get the following error messages:
error: unknown type name 'boolean_T'
error: 'false' undeclared (first use in this function)
error: 'true' undeclared (first use in this function)
I can ask for single file and add custom code with:
config_obj = coder.FilePArtitioningMethod('SingleFile');
config_obj.CustomSourceCode = ['typedef unsigned int boolean_T;',newline,...
'#define true 1U',newline,...
'#define false 0U'];
This will allow me to compile the code properly, but it's a crappy solution, since I don't want to generate a single file, and the added source is not included in every file as needed.
Is there any way I can avoid having the boolean_T type being used? Or there some directive I should have used but I'm missing?
boolean_T and possibly other types like int_T are defined in header files that are not generated, but shipped with MATLAB. Usually the definitions are in tmwtypes.h which you can find in /extern/include. The generated makefile includes a path to this in the list of include directories as an option to the compiler. If you are not using the generated makefile you would need to add the paths to these headers manually to your compiler options.
Using Dymola 2017.
Case A) Calling an external c-script
I have had success implementing simple external c functions that have no “# include <-->” statements:
Modelica Function:
function chirp
input Modelica.SIunits.AngularVelocity w_start;
input Modelica.SIunits.AngularVelocity w_end;
input Real A;
input Real M;
input Real t;
output Real u "output signal";
external "C" u=chirp(w_start,w_end,A,M,t)
annotation(IncludeDirectory="modelica://ExternalFuncTest/Resources/Source/", Include="#include \"chirp.c\"");
end chirp;
C-script:
double chirp(double w1, double w2, double A, double M, double time)
{
double res;
res=A*cos(w1*time+(w2-w1)*time*time/(2*M));
return res;
}
Case B) Calling an external function in a .dll file
I also have had success in calling external functions within a compiled dll:
Modelica Function:
function bessel_Jn
"Bessel function of the 1st kind (regular cylindrical) of order n"
extends Modelica.Icons.Function;
input Integer n;
input Real x;
output Real y;
external "C" y=gsl_sf_bessel_Jn(n,x) annotation(LibraryDirectory="modelica://ExternalFuncTest/Resources/Source/gsl-1.8/", Library="libgsl");
end bessel_Jn;
Case C) Calling an external c-script which uses functions from an external .dll via headers
What I want to do now is create a c function that does more interesting things. My current approach is to include header files in the c function that references the compiled dll (in this case a compiled version of the GNU scientific library). This example has the header (although it does not do anything for the moment).
Modelica Function:
function chirp
input Modelica.SIunits.AngularVelocity w_start;
input Modelica.SIunits.AngularVelocity w_end;
input Real A;
input Real M;
input Real t;
output Real u "output signal";
external "C" u=chirp(w_start,w_end,A,M,t)
annotation(LibraryDirectory="modelica://ExternalFuncTest/Resources/Source/gsl-1.8/", Library="libgsl",
IncludeDirectory="modelica://ExternalFuncTest/Resources/Source/", Include="#include \"chirp.c\"");
end chirp;
C-cript:
#include <gsl/gsl_sf_bessel.h> //<-- note the additional header
double chirp(double w1, double w2, double A, double M, double time)
{
double res;
res=A*cos(w1*time+(w2-w1)*time*time/(2*M));
return res;
}
When attempting to call the function above the error indicates failure to translate and nothing else due to the existence of the header file. If the header file is commented out the function will run as expected.
Please let me know if you have any insight as to how to properly go about implementing this feature. Thank you.
For reference: The image below is the path to the external c-script and .dll.
Wrong Path: Note gsl header folder is within gsl-1.8 folder
Correct Path: Note gsl header folder is at the same level as gsl-1.8 folder
UPDATE: Header works but function call causes translation to fail
I have updated the c-script to now call a function that should be handeled by the header. In its current state it won't work. Perhaps it can't find the .dll file although its specified in the modelica code? Do I have to include a load .dll command in the c-scripts?
#include <gsl/gsl_sf_bessel.h>
double chirp(double w1, double w2, double A, double M, double time)
{
double res;
double y;
res=A*cos(w1*time+(w2-w1)*time*time/(2*M));
y = gsl_sf_bessel_j0(time); // <-- Calls a function from the .dll file using the header
return res;
}
I believe this can only be resolved with relative include paths or future tools that implement future Modelica Language Specification 3.4. See https://trac.modelica.org/Modelica/ticket/2103 for the corresponding update on the Modelica Language Specification.
You set include directory to modelica://ExternalFuncTest/Resources/Source/gsl-1.8/
and then use #include <gsl-1.8/gsl/gsl_errno.h>
Do you really have a directory gsl-1.8 in the directory gsl-1.8 (some projects have such a structure - but it is generally rare)? If that is not the case change to #include <gsl/gsl_errno.h>.
I believe hierarchical includes are also searched in the path and thus that should work; otherwise you could always set includeDirectory to modelica://ExternalFuncTest/Resources/Source/gsl-1.8/gsl and use #include <gsl_errno.h>.
Referencing compiled library headers from c-scripts that are called by a Modelica external function call is possible.
However, it is still not determined if there is an efficient method to access the .dll. This is discussed in a follow up question External Functions: Alternative Method to use .dll from a C-script.
The solution that allowed the header files to be recognized is presented. Thanks to all who responded in helping figure this out.
Step 1) Create Folder Structure
Modelica looks in default directories automatically for external function dependencies. Section 12.9.4 of modelica.org/documents/ModelicaSpec33Revision1.pdf
The default location that Modelica looks for compiled libraries is a folder called Library within the Resources folder of your project:
LibraryDirectory="modelica://LibraryPackageName/Resources/Library"
For header files and c-scripts the default location is a folder called Include within the Resources folder of your project:
IncludeDirectory="modelica://LibraryPackageName/Resources/Include"
To specify alternative directories follow the modelica spec document. As of Modelica Specification 3.3 Rev 1 you can only specify one LibraryDirectory and one IncludeDirectory. Though this may be addressed in the future https://trac.modelica.org/Modelica/ticket/2103.
Summary of Overall Folder Structure
Step 2) Create Modelica Function and C-Scripts in locations specified in above image
Below are examples that can be used for reference.
Modelica Function
function chirp
input Modelica.SIunits.AngularVelocity w_start;
input Modelica.SIunits.AngularVelocity w_end;
input Real A;
input Real M;
input Real t;
output Real u "output signal";
external "C" u=chirp(w_start,w_end,A,M,t)
annotation(Library="libgsl",Include="#include \"chirp.c\"");
end chirp;
C-Script
#include <gsl/gsl_sf_bessel.h>
double chirp(double w1, double w2, double A, double M, double time)
{
double res;
res=A*cos(w1*time+(w2-w1)*time*time/(2*M));
return res;
}
I have a file funcs.m that stores anonymous functions. They must be usable by the files in the directory where it is. Currently, I use the anonymous functions so that I execute the file funcs.m in different files but I think this is a a wrong way of doing things. The other functions such as main.m and its nested function nest.m need to use the anonymous functions from funcs.m. I think paths won't solve this problem because the files are in the same folder. Basically I could solve this problem by copy-pasting the anonymous functions to every file but code-smell so:
Is there some way of reusing the funcs.m having the anon functions in Matlab?
Example
main.m
function main
funcs; % loads the anonymous functions
nest(par1,...,parN)
end
nest.m
function nest(par1,...,parN)
funcs; %ERRR: This fires err, why? Look: this was sourced already in main.m!
function neededOnlyHere(par100)
bq(q,A) %This needs the functions of the funcs
end
neededOnlyHere(somePar) %ERR to use the anon funcs from funcs
end
Functions main.m and nest.m use this function funcs.m having the anonymous funcs
bq=#(q,A) q*A; %Bolded q
I=#(ii,jj,A) find(A(ii,:)==1 & A(jj,:)==0);
AiNotj=zeros(1,Ncut);
...
ERROR
Attempt to add "bq" to a static workspace.
See MATLAB Programming, Restrictions on
Assigning to Variables for details.
Error in funcs (line 10)
bq=#(q,A) q*A;
%Bolded q
Why it's breaking
You get the error when calling it in nest.m because having a nested function makes its enclosing function's workspace a "static workspace"; that is, variable names cannot be added via eval(), assignin(), or other "dynamic" techniques; only variables that are explicitly assigned in that function's text are allowed. Evaluating a script to define local variables - which is what you're doing when calling funcs.m - is "dynamic", so prohibited in functions with nested functions. It works in main.m because main has no nested functions and is thus a "dynamic" workspace.
There are a couple ways you could change it to work with static workspaces and nested functions. The first thing to ask is whether you really need to make them anonymous functions?
Using package functions instead
If you don't need them to be anonymous functions per se, just break them out and put each one as a regular function in its own .m file; e.g. bg.m, I.m, AiNotj.m, and so on. Then they're all available to all other functions in that directory.
If that turns in to a mess of files, or if you want to scope them and maybe make them available only to the selected functions that really need them (that is, the functions currently calling funcs()), then you can stick them in a package. Create a subdirectory called +myfuncs and move all the little function files in there; e.g. +myfuncs/bq.m, +myfuncs/I.m, +myfuncs/AiNotj.m. (The + prefix tells Matlab the directory is a package.) Then you can pull all of them in to your function scope by doing import myfuncs.* as a direct replacement for where you're currently calling funcs().
function nest(par1,...,parN)
import myfuncs.*;
function neededOnlyHere(par100)
bq(q,A) % This will work, resolving to myfuncs.bq
end
You can do the import myfuncs.* from the command line to make them available interactively, too.
This is probably how Matlab itself wants you to organize clusters of related functions like this, and would be my first approach. It's the least "smelly" IMHO. If you really wanted to be able to edit them all in a single file like funcs.m for convenience, you could write a little code munger in Perl or whatever that parsed funcs.m and output them all as equivalent individual functions as a preprocessing step. (I think it's a bit of a bummer that you can't define multiple top-level functions in an M-file like this, but oh well.)
If you really need to work with anonymous functions, there are some workarounds.
Passing functions in a struct
You can change your funcs() function to actually return a struct of all those anonymous functions, using field names instead of local variable names.
function out = funcs
out.bq=#(q,A) q*A; %Bolded q
out.I=#(ii,jj,A) find(A(ii,:)==1 & A(jj,:)==0);
out.AiNotj=zeros(1,Ncut);
For this, you'd have to prefix all the function references with the struct name you're holding them in. Don't know how big a deal this is for you.
function nest(par1,...,parN)
fs = funcs;
function neededOnlyHere(par100)
fs.bq(q,A) %This needs the functions of the funcs
end
Preallocating variables
To get funcs() to work as-is, you can statically pre-allocate variables with all the function names you're going to use, so the Matlab parser recognizes them as statically assigned variables. Then when you call funcs(), it will re-assign the values of the existing variables, which is permissible in dynamic workspaces.
function nest(par1,...,parN)
[bq, I, AiNotj] = deal(); % Preallocate all names from funcs
funcs;
function neededOnlyHere(par100)
bq(q,A) %This needs the functions of the funcs
end
This would be a bit of a pain, because you'd have to re-edit every file that uses funcs whenever a new function name is added. You could at least write a little perl script to auto-generate that line of code by parsing funcs.m and outputting a "[bg, I, AiNotj,...] = deal();" with all the functions it finds, and you can just copy that in to your code.
Another way to do this would be to have funcs actually return all the functions in its output list. This would have the benefit of continuing to work even as you add new functions to funcs.m, as long as you don't remove or change the order of your existing anonymous functions.
function [bg,I,AiNotj] = funcs()
bg = ...
I = ...
% And then in the calling functions:
[bg,I,AiNotj] = funcs(); % which you can copy and paste from funcs.m's header
There are many ways of passing anonymous functions:
1) Pass the function itself:
function main
f = #(t) t^2 - 3;
param = randn(12,1);
g = test22(param,f);
disp (g)
end
function g = test22(param,f)
g = f(param(2));
disp(param(2))
end
2) Use globals (which usually should be avoided in complex code)
function main
global f
f = #(t) t^2 - 3;
param = randn(12,1);
g = test22(param);
disp (g)
end
function g = test22(param)
global f
g = f(param(2));
disp(param(2))
end
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."