Question

I'm trying to call a function in a native shared library from matlab using loadlibrary and calllib but I'm failing to obtain a string that is allocated from inside the library as char**.

Here is the (simplified) code of the native library:

#include <malloc.h>
#include <string.h>
#define DllExport __declspec(dllexport)

DllExport __int32 __stdcall MyFunction1()
{
    return 42;
}

DllExport __int32 __stdcall MyFunction2(__int32 handle, const char* format, char** info)
{
    *info = _strdup(format);
    return handle;
} 

And here is the (test) code from matlab side:

function [] = test()
%[
    loadlibrary('MyDll', @prototypes);

    try

        % Testing function 1
        val1 = calllib('MyDll', 'MyFunction1');
        disp(val1); % ==> ok the display value is 42

        % Testing function 2 
        info = libpointer('stringPtrPtr', {''});
        val2 = calllib('MyDll', 'MyFunction2', 666, 'kikou', info);    
        disp(val2); % ==> ok the value is 666
        disp(info.Value{1}); % ==> ko!! The value is still '' instead of 'kikou'

    catch
    end

    unloadlibrary('MyDll');
%]

%% --- Define prototypes for 'MyDll'
function [methodinfo, structs, enuminfo] = prototypes()
%[
    % Init
    ival = {cell(1,0)}; 
    fcns = struct('name',ival,'calltype',ival,'LHS',ival,'RHS',ival,'alias',ival);
    structs = []; enuminfo = []; fcnNum = 0;

    % Declaration for '__int32 __stdcall MyFunction1()'
    fcnNum = fcnNum+1; fcns.name{fcnNum} = 'MyFunction1'; fcns.calltype{fcnNum} = 'stdcall'; fcns.LHS{fcnNum} = 'int32'; fcns.RHS{fcnNum} = {};

    % Declaration for '__int32 __stdcall MyFunction2(__int32 handle, const char* format, char** info)'
    fcnNum = fcnNum+1; fcns.name{fcnNum} = 'MyFunction2'; fcns.calltype{fcnNum} = 'stdcall'; fcns.LHS{fcnNum} = 'int32'; fcns.RHS{fcnNum} = { 'int32', 'cstring', 'stringPtrPtr'};

    methodinfo = fcns;
%]

As you can see from prototypes sub-function, handle is marshaled as int32, format as cstring and info as stringPtrPtr. This is what by default perl's script creates from 'MyDll.h' and also what is suggested in this thread.

I've tried many other marshaling types but could not figure out how to obtain correct value for info.

NB: It is not reported here, but the native library also defines a function to free the memory allocated for info argument. My Matlab version is 7.2.0.232

Était-ce utile?

La solution

Last time I tried this, I discovered that input arguments of pointer types were not modified in place, instead additional output arguments were returned containing a copy of any pointer type input with any changes.

You can see this fact with:

>> libfunctions MyDll -full

Functions in library MyDll:

[int32, cstring, stringPtrPtr] MyFunction2(int32, cstring, stringPtrPtr)

The weird thing is that when I just tried this again on the latest R2013a, input arguments are indeed modified. Something must have changed since then :)

So in your case, you should call:

info = libpointer('stringPtrPtr',{''});
[val,~,info2] = calllib('MyDll', 'MyFunction2', 666, 'kikou', info)

and check the output info2

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top