Quantcast

Documentation Center

  • Trial Software
  • Product Updates

Working with Pointer Arguments

Pointer Arguments in C Functions

Many functions in external libraries pass arguments by reference. When you pass by reference, you pass a pointer to the value. In the function signature, these are the arguments with names ending in Ptr and PtrPtr. Although MATLAB® does not support passing by reference, you can create a MATLAB argument, called a lib.pointer object, that is compatible with a C pointer. This object is an instance of the MATLAB lib.pointer class.

In many cases, you can simply pass a MATLAB variable (passing an argument by value), even when the signature for that function declares the argument to be a pointer. There are times, however, when it is useful to pass a lib.pointer.

  • You want to modify the data in the input arguments.

  • You are passing large amounts of data, and you want to control when MATLAB makes copies of the data.

  • The library stores and uses the pointer for a period of time so you want the MATLAB function to control the lifetime of the lib.pointer object.

Creating a Pointer to a Primitive Type

The following example illustrates how to construct and pass a pointer, and how to interpret the output. It uses the multDoubleRef function in the shrlibsample library, which multiplies the input by 5. The input is a pointer to a double, and it returns a pointer to a double.

 multDoubleRef C Function

Construct a lib.pointer object, xp, to point to the input data, x.

x = 15;
xp = libpointer('doublePtr',x);

Verify the contents of xp:

get(xp)
       Value: 15
    DataType: 'doublePtr'

Now call the function and check the results:

calllib('shrlibsample','multDoubleRef',xp);
xp.Value
ans =
   75

The object xp is a handle object. All copies of this handle refer to the same underlying object and any operations you perform on a handle object affect all copies of that object. However, object xp is not a C language pointer. Although it points to x, it does not contain the address of x. The function modifies the Value property of xp but does not modify the value in the underlying object x. The original value of x is unchanged. Type:

x
x =
     15

Reading Function Return Values

In the previous example, the result of the function called from MATLAB could be obtained by examining the modified input pointer. But this function also returns data in its output arguments that may be useful.

To see the MATLAB signature for multDoubleRef, type:

libfunctions shrlibsample -full

 multDoubleRef Function Signature

The function returns two outputs—a lib.pointer object and the Value property of the input argument:

Run the example again:

x = 15;
xp = libpointer('doublePtr',x);

Check the output values:

[xobj,xval] = calllib('shrlibsample','multDoubleRef',xp)
xobj =
   lib.pointer
xval =
    75

Like the input argument xp, xobj is also a lib.pointer object. You can examine this output, but first you need to initialize its type and size because the function does not define these properties. Use the setdatatype method in the lib.pointer class to set the data type to doublePtr and the size to 1-by-1. Once initialized, you can examine outputs by typing:

setdatatype(xobj,'doublePtr',1,1)
get(xobj)
ans = 
       Value: 75
    DataType: 'doublePtr'

The second output of multDoubleRef, xval, is a copy of the Value property of input xp.

Creating a Pointer by Offsetting from an Existing lib.pointer Object

You can use the plus operator (+) to create a new pointer that is offset from an existing pointer by a scalar numeric value. For example, suppose you create a lib.pointer to the vector x:

x = 1:10;
xp = libpointer('doublePtr',x);
xp.Value
ans =
     1     2     3     4     5     6     7     8     9    10

Use the plus operator to create a new lib.pointer that is offset from xp:

xp2 = xp+4;
xp2.Value
ans =
     5     6     7     8     9    10

    Note:   The new pointer (xp2 in this example) is valid only as long as the original pointer, xp, exists.

Creating a Pointer to a Structure

If a function has an input argument that is a pointer to a structure, you can either pass the structure itself, or pass a pointer to the structure. Creating a pointer to a structure is similar to creating a pointer to a primitive type.

The addStructByRef function in the shrlibsample library takes a pointer to a structure of type c_struct. The output argument is the sum of all fields in the structure. The function also modifies the fields of the input structure.

 addStructByRef C Function

Passing the Structure Itself

Although the input to the addStructByRef function is a pointer to a structure, you can pass the structure itself and let MATLAB make the conversion to a pointer.

In the following example, create the structure sm and call addStructByRef:

sm.p1 = 476;   sm.p2 = -299;   sm.p3 = 1000;
x = calllib('shrlibsample','addStructByRef',sm)
x =
        1177

However, MATLAB does not modify the contents of sm, since it is not a pointer. Type:

sm
sm = 
    p1: 476
    p2: -299
    p3: 1000

Passing a Structure Pointer

The following example passes a pointer to the structure. First, create the lib.pointer object:

sp = libpointer('c_struct',sm);
sp.Value
ans = 
    p1: 476
    p2: -299
    p3: 1000

The lib.pointer, sp, has the same values as the structure sm.

Pass the lib.pointer to the function:

if not(libisloaded('shrlibsample'))
    addpath(fullfile(matlabroot,'extern','examples','shrlib'));
    loadlibrary('shrlibsample')
end
calllib('shrlibsample','addStructByRef',sp)
ans =
        1177

In this case, the function modifies the structure fields. Type:

sp.Value
ans = 
    p1: 5.5000
    p2: 1234
    p3: 12345678

MATLAB displays the updated values.

Passing a Pointer to the First Element of an Array

In cases where a function defines an input argument that is a pointer to the first element of a data array, MATLAB automatically passes an argument that is a pointer of the correct type to the first element of data in the MATLAB vector or matrix.

The following pseudo-code shows how to do this. Suppose you have a function mySum in a library myLib. The signature of the C function is:

Return TypeNameArguments
intmySum(int size,
short* data)

The C variable data is an array of type short. The equivalent MATLAB type is int16. You can pass any of the following MATLAB variables to this function:

Data = 1:100;
shortData = int16(Data); %equivalent to C short type
lp = libpointer('int16Ptr',Data); %libpointer object

The following pseudo-code statements are equivalent:

summed_data = calllib('myLib','mySum',100,Data);
summed_data = calllib('myLib','mySum',100,shortData);
summed_data = calllib('myLib','mySum',100,lp);

The length of the data vector must be equal to the specified size. For example:

% sum last 50 elements
summed_data = calllib('myLib','mySum',50,Data(51:100)); 

Putting a String into a Void Pointer

C represents characters as eight-bit integers. To use a MATLAB string as an input argument, you must convert the string to the proper type and create a voidPtr. To do this, use the libpointer function as follows:

str = 'string variable';
vp = libpointer('voidPtr',[int8(str) 0]);

The syntax [int8(str) 0] creates the null-terminated string required by the C function. To read the string, and verify the pointer type, enter:

char(vp.Value)
vp.DataType
ans = 
string variable
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 pointer:

func_name([int8(str) 0])

Note that while MATLAB converts the argument from a value to a pointer, it must be of the correct type.

Passing an Array of Strings

The getListOfStrings function from the shrlibsample library returns a char **, which you can think of as a pointer to an array of strings.

 getListOfStrings Function Signature

 getListOfStrings C Function

To read this array, type:

if not(libisloaded('shrlibsample'))
    addpath(fullfile(matlabroot,'extern','examples','shrlib'));
    loadlibrary('shrlibsample')
end
ptr = calllib('shrlibsample','getListOfStrings');

MATLAB creates a lib.pointer object ptr of type stringPtrPtr. This object points to the first string. To display the string, use the Value property:

ptr.Value

To view the other strings, you need to increment the pointer. For example, type:

for index = 0:3
  tempPtr = ptr + index;
  tempPtr.Value
end 
ans = 
    'String 1'
ans = 
    'String Two'
ans = 
    {''}
ans = 
    'Last string'

For another example, see Iterate Through an Array.

Memory Allocation for an External Library

In general, MATLAB passes a valid memory address each time you pass a variable to a library function. You should use a lib.pointer object in cases where the library stores the pointer and accesses 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 a lib.pointer in this situation.

Suppose an external library myLib has the following functions:

AcquireData(int points,short *buffer)
IsAquisitionDone(void)

where buffer is declared as follows:

short buffer[99]

First, create a lib.pointer to an array of 99 points:

BufferSize = 99;
pBuffer = libpointer('int16Ptr',zeros(BufferSize,1));

Then, begin acquiring data and wait in a loop until it is done:

calllib('myLib','AcquireData,BufferSize,pbuffer);
while (~calllib('myLib','IsAcquisitionDone')
  pause(0.1)
end

The 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

Multilevel Pointers

Multilevel pointers are arguments that have more than one level of referencing. A multilevel pointer type in MATLAB uses the suffix PtrPtr. For example, use doublePtrPtr for the C argument double **.

When calling a function that takes a multilevel pointer argument, use a lib.pointer object and let MATLAB convert it to the multilevel pointer. For example, the allocateStruct function in the shrlibsample library takes a c_structPtrPtr argument.

 allocateStruct Function Signature

 allocateStruct C Function

Create a lib.pointer object of type c_structPtr and pass it to the function:

if not(libisloaded('shrlibsample'))
  addpath(fullfile(matlabroot,'extern','examples','shrlib'));
  loadlibrary('shrlibsample')
end
sp = libpointer('c_structPtr');
calllib('shrlibsample','allocateStruct',sp)
get(sp)
ans = 
       Value: [1x1 struct]
    DataType: 'c_structPtr'

Type:

sp.Value
ans = 
    p1: 12.4000
    p2: 222
    p3: 333333

When you use allocateStruct, you must free memory using the command:

calllib('shrlibsample','deallocateStruct',sp)

Returning an Array of Strings

Suppose you have a library, myLib, with a function, acquireString, that reads an array of strings. The function signature is:

Return TypeNameArguments
char**acquireString(void)

char** acquireString(void)

The following pseudo-code shows how to manipulate the return value, an array of pointers to strings.

ptr = calllib(myLib,'acquireString');

MATLAB creates a lib.pointer object ptr of type stringPtrPtr. This object points to the first string. To view other strings, you need to increment the pointer. For example, to display the first 3 strings, type:

for index = 0:2
  tempPtr = ptr + index;
  tempPtr.Value
end 
ans = 
    'str1'
ans = 
    'str2'
ans = 
    'str3'
Was this topic helpful?