Передача аргумента указателя в MATLAB в функцию C-DLL foo (char **) - PullRequest
5 голосов
/ 16 сентября 2011

Я пишу C-DLL для вызова из MATLAB. Можно ли вызвать функцию с параметром const char **? например,

void myGetVersion( const char ** );

Код C будет:

const char *version=0;
myGetVersion( &version );

Каким будет соответствующий MATLAB-код (если это вообще возможно)?

Большое спасибо!

P.S .: Я думаю это страница справки , но я не смог найти свой случай: - (

Ответы [ 3 ]

8 голосов
/ 16 сентября 2011

Ответ заключается в создании указателя на c-строку с использованием функции LIBPOINTER , как предложено @ JonasHeidelberg .Позвольте мне расширить его решение рабочим примером.

Сначала давайте создадим простую 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");
}

Вы можете использовать предпочитаемый компилятор для создания библиотеки DLL (Visual Studio, MinGW GCC, ..).Я использую MinGW для компиляции выше, вот что я использую make-файл:

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

Прежде чем мы перейдем к MATLAB, давайте протестируем библиотеку с программой на C:

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;
}

Теперь, когда все работает, вот как использовать эту библиотеку из 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

Вывод с возвращенной строкой:

Functions in library libversion:
stringPtrPtr myGetVersion(stringPtrPtr)

       Value: {''}
    DataType: 'stringPtrPtr'

dllVersion =
1.0.0
3 голосов
/ 16 сентября 2011

Глядя на Работа с указателями , раздел Передача массива строк в документации MATLAB (ссылки на которую можно найти на странице справки, на которую вы ссылались в своем вопросе), кажется, вам нужно построить объект libpointer в MATLAB, что-то вроде

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

(У меня нет библиотеки DLL для проверки этого прямо сейчас, и я не очень хорошо разбираюсь в C-указателях, так что нет гарантии ... надеюсь, это шаг в правильном направлении)

0 голосов
/ 07 августа 2017

Я не смог заставить работать решение @ Amro (старая версия MATLAB?).Итак, мне пришлось сделать что-то более креативное:

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))
...