| MATLAB® | ![]() |
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 pass 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 stores and uses the pointer for a period of time so you want the M-code to control the lifetime of the pointer object.
In these cases, you can use the libpointer function 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')For example, create a pointer pv to an int16 value. The type of pointer you are creating 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 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
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 =
15In 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.
You can use the plus operator (+) to create a new pointer that is offset from an existing pointer by a scalar numeric value. This operation applies only to pointers 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;
}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 =
1177The 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 in library libname is:
int sum(int size, short* data);
The following statements 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);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
To confirm the pointer type, 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.
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 libfunctions -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. Type:
libfunctions shrlibsample -full
Look for the following allocateStruct signature:
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 to Shared Library Functions | Working with Structures | ![]() |
| © 1984-2008- The MathWorks, Inc. - Site Help - Patents - Trademarks - Privacy Policy - Preventing Piracy - RSS |