Passing pointer argument in MATLAB to a C-DLL function foo(char**)

前端 未结 3 754
感情败类
感情败类 2020-12-10 18:20

I am writing a C-DLL to be called from MATLAB. Is it possible to call a function with const char ** parameter? e.g.

void myGetVersion( const ch         


        
相关标签:
3条回答
  • 2020-12-10 18:46

    The answer is to build a pointer to a c-string using the LIBPOINTER function as @JonasHeidelberg suggested. Let me expand his solution with a working example..

    First lets build a simple DLL:

    version.h

    #ifndef VERSION_H
    #define VERSION_H
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    #ifdef _WIN32
    #   ifdef BUILDING_DLL
    #       define DLL_IMPORT_EXPORT __declspec(dllexport)
    #   else
    #       define DLL_IMPORT_EXPORT __declspec(dllimport)
    #   endif
    #else
    #   define DLL_IMPORT_EXPORT
    #endif
    
    DLL_IMPORT_EXPORT void myGetVersion(char**str);
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif
    

    version.c

    #include "version.h"
    #include <string.h>
    
    DLL_IMPORT_EXPORT void myGetVersion(char **str)
    {
        *str = strdup("1.0.0");
    }
    

    You can use your preferred compiler to build the DLL library (Visual Studio, MinGW GCC, ..). I am using MinGW to compile the above, here is the makefile I am using:

    Makefile

    CC = gcc
    
    all: main
    
    libversion.dll: version.c
        $(CC) -DBUILDING_DLL version.c -I. -shared -o libversion.dll
    
    main: libversion.dll main.c
        $(CC) main.c -o main -L. -lversion
    
    clean:
        rm -rf *.o *.dll *.exe
    

    Before we move to MATLAB, lets test the library with a C program:

    main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include "version.h"
    
    int main()
    {
        char *str = NULL;
        myGetVersion(&str);
        printf("%s\n", str);
        free(str);
    
        return 0;
    }
    

    Now that all is working, here is how to use this library from MATLAB:

    testDLL.m

    %# load DLL and check exported functions
    loadlibrary libversion.dll version.h
    assert( libisloaded('libversion') )
    libfunctions libversion -full
    
    %# pass c-string by reference
    pstr = libpointer('stringPtrPtr',{''}); %# we use a cellarray of strings
    get(pstr)
    calllib('libversion','myGetVersion',pstr)
    dllVersion = pstr.Value{1}
    
    %# unload DLL
    unloadlibrary libversion
    

    The output with the string returned:

    Functions in library libversion:
    stringPtrPtr myGetVersion(stringPtrPtr)
    
           Value: {''}
        DataType: 'stringPtrPtr'
    
    dllVersion =
    1.0.0
    
    0 讨论(0)
  • 2020-12-10 18:49

    Looking at Working with pointers, section Passing an Array of Strings in the MATLAB documentation (linked from the help page you linked in your question), it seems you need to construct a libpointer object in MATLAB, something like

    version = libpointer('stringPtrPtr',{''}); %# corrected according to Amro's comment
    calllib('yourCdll', 'myGetVersion', version)
    

    (I don't have a DLL to test this with right now, and I'm not very firm on C pointers, so no guarantee... hope this is a step in the right direction)

    0 讨论(0)
  • 2020-12-10 18:52

    I could not get @Amro's solution to work (old version of MATLAB?). So, I had to do something a little more creative:

    pstr = libpointer('voidPtr');
    ret = calllib('libversion', 'myGetVersion', pstr);
    % establish the length
    n = 0;
    while n==0 || pstr.Value(n) ~= 0
        n=n+1;
        pstr.setdatatype('uint8Ptr', 1, n);
    end
    % truncate to exclude the NULL character
    pstr.setdatatype('uint8Ptr', 1, n-1);
    % convert to string
    display(char(pstr.Value))
    
    0 讨论(0)
提交回复
热议问题