| MATLAB® | ![]() |
| On this page… |
|---|
Under most conditions, MATLAB® software automatically converts data passed to and from external library functions to the data type expected by the external function. However, you may choose, at times, to convert some of your argument data manually. Circumstances under which you might find this advantageous are:
When you pass the same piece of data to a series of library functions, it probably makes more sense to convert it once manually at the start rather than having MATLAB convert it automatically on every call. This saves time on unnecessary copy and conversion operations.
When you pass large structures, you can save memory by creating MATLAB structures that match the shape of the C structures used in the external function instead of using generic MATLAB structures. The libstruct function creates a MATLAB structure modeled from a C structure taken from the library. See Structures for more information.
When an argument to an external function uses more than one level of referencing (e.g., double **), you must pass a reference that you have constructed using the libpointer function rather than relying on MATLAB to convert the data type automatically.
The shared library interface supports all standard scalar C data types. The following tables show these C types with their equivalent MATLAB types. MATLAB uses the type from the right column for arguments having the C type shown in the left column.
The second table shows extended MATLAB types in the right column. These are instances of the MATLAB lib.pointer class rather than standard MATLAB types. See Creating References for information on the lib.pointer class.
MATLAB® Primitive Types
| C Type | Equivalent MATLAB Type |
|---|---|
char, byte | int8 |
unsigned char, byte | uint8 |
short | int16 |
unsigned short | uint16 |
int | int32 |
long (32-bit) | int32 |
long (64-bit) | int64 |
unsigned int, unsigned long | uint32 |
float | single |
double | double |
char * | cstring (1xn char array) |
*char[] | cell array of strings |
MATLAB® Extended Types
| C Type | Equivalent MATLAB Type |
|---|---|
integer pointer types (int *) | (u)int(size)Ptr |
Null-terminated string passed by value | cstring |
Null-terminated string passed by reference (from a libpointer only) | stringPtr |
Array of pointers to strings (or one **char) | stringPtrPtr |
Matrix of signed bytes | int8Ptr |
float * | singlePtr |
double * | doublePtr |
mxArray * | MATLAB array |
void * | voidPtr |
void ** | voidPtrPtr |
type ** | Same as typePtr with an added Ptr (e.g., double ** |
For primitive types, MATLAB automatically converts any argument to the data type expected by the external function. This means that you can pass a double to a function that expects to receive a byte (8-bit integer) and MATLAB does the conversion for you.
For example, the C function shown here takes arguments that are of types short, int, and double:
double addMixedTypes(short x, int y, double z)
{
return (x + y + z);
}You can simply pass all of the arguments as type double from MATLAB. MATLAB determines what type of data is expected for each argument and performs the appropriate conversions. For example, type:
calllib('shrlibsample', 'addMixedTypes', 127, 33000, pi)
MATLAB displays:
ans = 3.3130e+004
MATLAB also automatically converts an argument passed by value into an argument passed by reference when the external function prototype defines the argument as a reference. So a MATLAB double argument passed to a function that expects double * is converted to a double reference by MATLAB.
addDoubleRef is a C function that takes an argument of type double *:
double addDoubleRef(double x, double *y, double z)
{
return (x + *y + z);
}Call the function with three arguments of type double, and MATLAB handles the conversion:
calllib('shrlibsample', 'addDoubleRef', 1.78, 5.42, 13.3)
MATLAB displays:
ans = 20.5000
For arguments that require char *, you can pass a MATLAB string (i.e., character array).
For example, the following C function takes a char * input argument:
char* stringToUpper(char *input) {
char *p = input;
if (p != NULL)
while (*p!=0)
*p++ = toupper(*p);
return input;
}libfunctions shows that you can use a MATLAB cstring for this input.
libfunctions shrlibsample -full
.
.
[cstring, cstring] stringToUpper(cstring)Create a MATLAB character array, str, and pass it as the input argument:
str = 'This was a Mixed Case string';
calllib('shrlibsample', 'stringToUpper', str)
MATLAB displays:
ans = THIS WAS A MIXED CASE STRING
Note Although the input argument that MATLAB passes to stringToUpper resembles a reference to type char, it is not a true reference data type. That is, it does not contain the address of the MATLAB character array, str. So, when the function executes, it returns the correct result but does not modify the value in str. If you now examine str, you find that its original value is unchanged. Type: str MATLAB displays: str = This was a Mixed Case string |
For arguments defined as C enumerated types, you can pass either the enumeration string or its integer equivalent.
The readEnum function from the shrlibsample library returns the enumeration string that matches the argument passed in. Here is the Enum1 definition and the readEnum function in C:
enum Enum1 {en1 = 1, en2, en4 = 4} TEnum1;
char* readEnum(TEnum1 val) {
switch (val) {
case 1 :return "You chose en1";
case 2: return "You chose en2";
case 4: return "You chose en4";
default : return "enum not defined";
}
}In MATLAB, you can express an enumerated type as either the enumeration string or its equivalent numeric value. The TEnum1 definition above declares enumeration en4 to be equal to 4. Call readEnum first with a string:
calllib('shrlibsample', 'readEnum', 'en4')
MATLAB displays:
ans = You chose en4
Now call it with the equivalent numeric argument, 4:
calllib('shrlibsample', 'readEnum', 4)
MATLAB displays:
ans = You chose en4
For library functions that take structure arguments, you need to pass structures that have field names that are the same as those in the structure definitions in the library. To determine the names and also the data types of structure fields, you can:
Consult the documentation that was provided with the library.
Look for the structure definition in the header file that you used to load the library into MATLAB.
When you create and initialize the structure, you do not necessarily have to match the data types of numeric fields. MATLAB converts to the correct numeric type for you when you make the call using the calllib function.
You can also determine the field names of an externally defined structure from MATLAB using the following procedure:
Use libfunctionsview to display the signatures for all functions in the library. libfunctionsview shows the names of the structures used by each function. For example, when you type:
libfunctionsview shrlibsample
MATLAB opens a new window displaying function signatures for the shrlibsample library. The line showing the addStructFields function reads:
double addStructFields (c_struct)
If the function you are using takes a structure argument, get the structure type from the libfunctionsview display, and invoke the libstruct function on that type. libstruct returns an object that is modeled on the structure as defined in the library:
s = libstruct('c_struct');Get the names of the structure fields from the object returned by libstruct. Type:
get(s)
MATLAB displays:
p1: 0
p2: 0
p3: 0Initialize the fields to the values you want to pass to the library function and make the call using calllib:
s.p1 = 476; s.p2 = -299; s.p3 = 1000;
calllib('shrlibsample','addStructFields',s);Here are a few general guidelines that apply to structures passed to external library functions:
These structures can contain fewer fields than defined in the library structure. MATLAB sets any undefined or uninitialized fields to zero.
Any structure field name that you use must match a field name in the structure definition. Structure names are case sensitive.
Structures cannot contain additional fields that are not in the library structure definition.
As with other data types, when an external function takes a structure argument (such as a C structure), you can pass a MATLAB structure to the function in its place. Structure field names must match field names defined in the library, but data types for numeric fields do not have to match. MATLAB converts each numeric field of the MATLAB structure to the correct data type.
Example of Passing a MATLAB® Structure. The sample shared library, shrlibsample, defines the following C structure and function:
struct c_struct {
double p1;
short p2;
long p3;
};
double addStructFields(struct c_struct st)
{
double t = st.p1 + st.p2 + st.p3;
return t;
}The following code passes a MATLAB structure, sm, with three double fields to addStructFields. MATLAB converts the fields to the double, short, and long data types defined in the C structure, c_struct. For example, type
sm.p1 = 476; sm.p2 = -299; sm.p3 = 1000;
calllib('shrlibsample', 'addStructFields', sm)
MATLAB displays:
ans =
1177When you pass a structure to an external function, MATLAB makes sure that the structure being passed matches the library's definition for that structure type. It must contain all the necessary fields defined for that type and each field must be of the expected data type. For any fields that are missing in the structure being passed, MATLAB creates an empty field of that name and initializes its value to zero. For any fields that have a data type that doesn't match the structure definition, MATLAB converts the field to the expected type.
When working with small structures, it is efficient enough to have MATLAB do this work for you. You can pass the original MATLAB structure with calllib and let MATLAB handle the conversions automatically. However, when working with repeated calls that pass one or more large structures, it may be to your advantage to convert the structure manually before making any calls to external functions. In this way, you save processing time by converting the structure data only once at the start rather than at each function call. You can also save memory if the fields of the converted structure take up less space than the original MATLAB structure.
Preconverting a MATLAB® Struct with libstruct. You can convert a MATLAB structure to a C-style structure derived from a specific type definition in the library in one step. Call the libstruct function, passing in the name of the structure type from the library, and the original structure from MATLAB. The syntax for libstruct is:
s = libstruct('structtype', mlstruct)The value s returned by this function is called a libstruct object. Although it is truly a MATLAB object, it handles much like a MATLAB structure. The fields of this new "structure" are derived from the external structure type specified by structtype in the syntax above.
For example, to convert a MATLAB structure, sm, to a libstruct object, sc, that is derived from the c_struct structure type, use:
sm.p1 = 476; sm.p2 = -299; sm.p3 = 1000;
sc = libstruct('c_struct', sm);All of fields in the original structure sm are of type double. The object sc, returned from the libstruct function, has fields that match the c_struct structure type. These fields are double, short, and long.
Note You can only use libstruct on scalar structures. |
Creating an Empty libstruct Object. You can also create an empty libstruct object by calling libstruct with only the structtype argument. The following statement constructs an object with all the required fields and with each field initialized to zero:
s = libstruct('structtype')libstruct Requirements for Structures. When converting a MATLAB structure to a libstruct object, the structure to be converted must adhere to the same guidelines that were documented for MATLAB structures passed directly to external functions. See Specifying Structure Field Names.
The value returned by libstruct is not a true MATLAB structure. It is actually an instance of a class called lib.c_struct, as seen by examining the output of whos. Type:
whos
MATLAB displays (in part):
Name Size Bytes Class sc 1x1 lib.c_struct sm 1x1 396 struct array
Determining the Size of a lib.c_struct Object. You can use the lib.c_struct class method structsize to obtain the size of a lib.c_struct object:
sc.structsize
MATLAB displays:
ans = 16
Accessing lib.c_struct Fields. The fields of this structure are implemented as properties of the lib.c_struct class. You can read and modify any of these fields using the MATLAB object-oriented functions, set and get:
sc = libstruct('c_struct');
set(sc, 'p1', 100, 'p2', 150, 'p3', 200);
get(sc)
MATLAB displays:
p1: 100
p2: 150
p3: 200You can also read and modify the fields by simply treating them like any other MATLAB structure fields:
sc.p1 = 23; sc.p1
MATLAB displays:
ans = 23
Repeat the addStructFields example, this time converting the structure to one of type c_struct before calling the function:
sm.p1 = 476; sm.p2 = -299; sm.p3 = 1000;
sc = libstruct('c_struct', sm);
get(sc)
MATLAB displays:
p1: 476
p2: -299
p3: 1000
Now call the function, passing the structure sc:
calllib('shrlibsample', 'addStructFields', sc)
MATLAB displays:
ans =
1177
Note When passing manually converted structures, the structure passed must be of the same type as that used by the external function. For example, you cannot pass a structure of type records to a function that expects type c_struct. |
You can pass most arguments to an external function by value, even when the prototype for that function declares the argument to be a reference. The calllib function uses the header file to determine how to convert the function arguments.
There are times, however, when it is useful to pass MATLAB arguments that are the equivalent of C references:
You want to modify the data in the input arguments.
You are passing large amounts of data, and you don't want MATLAB to make copies of the data.
The library is going to store and use the pointer for a period of time so it is better to give the M-code control over the lifetime of the pointer object.
In the cases above, you should use libpointer to construct a pointer object of a specified type (for structures use libstruct).
To construct a reference, use the function libpointer with this syntax:
p = libpointer('type', 'value')To give an example, create a pointer pv to an int16 value. In the first argument to libpointer, enter the type of pointer you are creating. The type is always the data type (int16, in this case) suffixed by the letters Ptr:
v = int16(485);
pv = libpointer('int16Ptr', v);The value pv is an instance of a MATLAB lib.pointer class. The lib.pointer class has the properties Value and DataType. You can read and modify these properties with the MATLAB get and set functions:
get(pv)
MATLAB displays:
Value: 485
DataType: 'int16Ptr'The lib.pointer class method setdatatype is described in Obtaining the Function's Return Values:
methods(pv)
MATLAB displays:
Methods for class lib.pointer: disp plus setdatatype isNull reshape
The following example illustrates how to construct and pass a pointer to type double, and how to interpret the output data. The function multDoubleRef takes one input that is a reference to a double and returns the same.
Here is the C function:
double *multDoubleRef(double *x)
{
*x *= 5;
return x;
}Construct a reference, xp, to input data, x, and verify its contents:
x = 15;
xp = libpointer('doublePtr', x);
get(xp)
MATLAB displays:
Value: 15
DataType: 'doublePtr'Now call the function and check the results:
calllib('shrlibsample', 'multDoubleRef', xp);
get(xp, 'Value')
MATLAB displays:
ans = 75
Note Reference xp is not a true pointer as it would be in a language like C. That is, even though it was constructed as a reference to x, it does not contain the address of x. So, when the function executes, it modifies the Value property of xp, but it does not modify the value in x. If you now examine x, you find that its original value is unchanged: x
x =
15 |
Obtaining the Function's Return Values. In the previous example, the result of the function called from MATLAB could be obtained by examining the modified input reference. But this function also returns data in its output arguments that may be useful.
The MATLAB prototype for this function (returned by libfunctions -full) indicates that MATLAB returns two outputs. The first is an object of class lib.pointer; the second is the Value property of the doublePtr input argument:
libfunctions shrlibsample -full [lib.pointer, doublePtr] multDoubleRef(doublePtr)
Run the example once more, but this time check the output values returned:
x = 15;
xp = libpointer('doublePtr', x);
[xobj, xval] = calllib('shrlibsample', 'multDoubleRef', xp)
MATLAB displays:
xobj =
lib.pointer
xval =
75Like the input reference argument, the first output, xobj, is an object of class lib.pointer. You can examine this output, but first you need to initialize its data type and size as these factors are undefined when returned by the function. Use the setdatatype method defined by class lib.pointer to set the data type to doublePtr and the size to 1-by-1. Once initialized, you can examine outputs.
The first output is xobj:
setdatatype(xobj, 'doublePtr', 1, 1) get(xobj)
MATLAB displays:
ans =
Value: 75
DataType: 'doublePtr'The second output, xval, is a double copied from the Value of input xp.
Creating a Reference by Offsetting from an Existing libpointer. You can use the plus operator (+) to create a new pointer that is offset from an existing pointer by a scalar numeric value. Note that this operation applies only to pointer of numeric data types. For example, suppose you create a libpointer to the vector x:
x = 1:10;
xp = libpointer('doublePtr',x);
xp.Value
MATLAB displays:
ans =
1 2 3 4 5 6 7 8 9 10You can now use the plus operator to create a new libpointer that is offset from the xp:
xp2 = xp+4; xp2.Value
MATLAB displays:
ans =
5 6 7 8 9 10Note that the new pointer (xp2 in this example) is valid only as long as the original pointer exists.
Creating a reference argument to a structure is not much different than using a reference to a primitive type. The function shown here takes a reference to a structure of type c_struct as its only input. It returns an output argument that is the sum of all fields in the structure. It also modifies the fields of the input argument:
double addStructByRef(struct c_struct *st)
{
double t = st->p1 + st->p2 + st->p3;
st->p1 = 5.5;
st->p2 = 1234;
st->p3 = 12345678;
return t;
}Passing the Structure Itself. Although this function expects to receive a structure reference input, it is easier to pass the structure itself and let MATLAB do the conversion to a reference. This example passes a MATLAB structure, sm, to the function addStructByRef. MATLAB returns the correct value in the output, x, but does not modify the contents of the input, sm, since sm is not a reference:
sm.p1 = 476; sm.p2 = -299; sm.p3 = 1000;
x = calllib('shrlibsample', 'addStructByRef', sm)
MATLAB displays:
x =
1177Passing a Structure Reference. The second part of this example passes the structure by reference. This time, the function receives a pointer to the structure and is then able to modify the structure fields.
sp = libpointer('c_struct', sm);
calllib('shrlibsample', 'addStructByRef', sp)
MATLAB displays:
ans =
1177
Type:
get(sp, 'Value')
MATLAB displays:
ans =
p1: 5.5000
p2: 1234
p3: 12345678In cases where a function defines an input argument that is a pointer to the first element of a data array, the calllib function automatically passes an argument that is a pointer of the correct type to the first element of data in the MATLAB vector or matrix. For example, the following C function sum requires an argument that is a pointer to the first element of an array of shorts (int16).
Suppose you define the following MATLAB variables :
Data = 1:100;
lp = libpointer('int16Ptr',Data);
shortData = int16(Data);The signature of the C function sum is:
int sum(int size, short* data);
All of the following statements work correctly and give the same answer:
summed_data = calllib('libname','sum',100,Data);
summed_data = calllib('libname','sum',100,shortData);
summed_data = calllib('libname','sum',100,lp);Note that the size and data arguments must match. That is, length of the data vector must be equal to the specified size. For example:
% sum last 50 elements
summed_data = calllib('libname','sum',50,Data(50:100)); Suppose you want to create a voidPtr that points to a string as an input argument. In C, characters are represented as unsigned eight-bit integers. Therefore, you must first cast the string to this MATLAB type before creating a variable of type voidPtr.
You can create a variable of the correct type and value using libpointer as follows:
str = 'string variable';
vp = libpointer('voidPtr',[uint8(str) 0]);To obtain the character string from the pointer, type:
char(vp.Value)
MATLAB displays:
ans = string variable
Confirm the type of the pointer by accessing its DataType property, type:
vp.DataType
MATLAB displays:
ans = voidPtr
You can call a function that takes a voidPtr to a string as an input argument using the following syntax because MATLAB automatically converts an argument passed by value into an argument passed by reference when the external function prototype defines the argument as a reference:
func_name(uint8(str))Note that while MATLAB converts the argument from a value to a reference, it must be of the correct type.
In general, a valid memory address is passed each time you pass a MATLAB variable to a library function. You need to explicitly allocate memory only if the library provides a memory allocation function that you are required to use.
When to Use libpointer. You should use a libpointer object in cases where the library is going to store the pointer and access the buffer over a period of time. In these cases, you need to ensure that MATLAB has control over the lifetime of the buffer and to prevent copies of the data from being made. The following pseudo code is an example of asynchronous data acquisition that shows how to use libpointer in this type of situation.
Suppose an external library has the following functions:
AcquireData(int points, short *buffer) IsAquistionDone(void)
First, create a pointer to a buffer of 1024 points:
BufferSize = 1024;
pBuffer = libpointer('int16Ptr',1:BufferSize);Then, begin acquiring data and wait in a loop until it is done:
calllib('lib_name','AcquireData,BufferSize,pbuffer);
while (~calllib('lib_name','IsAcquisitionDone')
pause(0.1)
endThe following statement reads the data in the buffer:
result = pBuffer.Value;
When the library is done with the buffer, clear the MATLAB variable:
clear pBuffer
Arguments that have more than one level of referencing (e.g., uint16 **) are referred to here as reference pointers. In MATLAB, these argument types are named with the suffix PtrPtr (for example, uint16PtrPtr). See the output of libfunctionsview or methods -full for examples of this type.
When calling a function that takes a reference pointer argument, you can use a reference argument instead and MATLAB converts it to the reference pointer. For example, the external allocateStruct function expects a c_structPtrPtr argument:
libfunctions shrlibsample -full c_structPtrPtr allocateStruct(c_structPtrPtr)
Here is the C function:
void allocateStruct(struct c_struct **val)
{
*val=(struct c_struct*) malloc(sizeof(struct c_struct));
(*val)->p1 = 12.4;
(*val)->p2 = 222;
(*val)->p3 = 333333;
}Although the prototype says that a c_structPtrPtr is required, you can use a c_structPtr and let MATLAB do the second level of conversion. Create a reference to an empty structure argument and pass it to allocateStruct:
sp = libpointer('c_structPtr');
calllib('shrlibsample', 'allocateStruct', sp)
get(sp)
MATLAB displays:
ans =
Value: [1x1 struct]
DataType: 'c_structPtr'
Type:
get(sp, 'Value')
MATLAB displays:
ans =
p1: 12.4000
p2: 222
p3: 333333Free memory using the command:
calllib('shrlibsample', 'deallocateStruct', sp)
![]() | Passing Arguments | Calling C and Fortran Programs from MATLAB® Command Line | ![]() |
| © 1984-2008- The MathWorks, Inc. - Site Help - Patents - Trademarks - Privacy Policy - Preventing Piracy - RSS |