mkoctfile с несколькими исходными файлами C и C ++ - PullRequest
0 голосов
/ 15 января 2019

У меня нет возможности mkoctfile для успешного создания файла oct, который является оболочкой для какой-то моей C++ функции (например, void my_fun(double*,double)). В частности, моя проблема возникает из-за того, что код оболочки my_fun_wrap.cpp требует включения библиотеки <octave/oct.h>, которая предоставляет только заголовки C++ (см. здесь ), но оригинальный код my_fun также использует исходный код, который находится в C. Э.Г.

// my_fun_wrapper.cpp

#include <octave/oct.h>
#include "custom_functions_libc.h"

DEFUN_DLD(my_fun_wrapper,args, , "EI MF network model A with delays (Brunel, JCN 2000)"){

// Input arguments
NDArray xvar = args(0).array_value();
double x = xvar(0);

// Output arguments
double dy[4];
dim_vector dv (4,1);
NDArray dxvars(dv);

// Invoke my C function which also includes code in the lib file custom_functions_libc.c  
my_fun(dy,x);

// Then assign output value to NDArray
for(int i=0;i<4;i++) dxvars(i) = dy[i];

// Cast output as octave_value as required by the octave guidelines
return octave_value (dxvars);
}

Тогда предположим, что мои custom_functions_libc.h и custom_functions_libc.c файлы находятся где-то в папке <path_to_folder>/my_libs. В идеале, из командной строки Octave я бы скомпилировал вышеперечисленное:

mkoctfile -g -v -O -I<path_to_folder>/my_libs <path_to_folder>/my_libs/custom_functions_libc.c my_fun_wrapper.cpp -output my_fun_wrapper -lm -lgsl -lgslcblas 

Это фактически генерирует my_fun_wrapper.oct, как требуется. Затем я могу назвать этот последний из некоторого кода octave, например

...
... 
xx = [0., 2.5, 1.];
yy = [1e-5, 0.1, 2.];    

dxv = test_my_function(xx,yy);


function dy = test_my_function(xx,yy)
    xx += yy**2;
    dy = my_fun_wrapper(xx);        
endfunction

Оказывается, что вышеприведенный код завершится с ошибкой в ​​test_my_function, говорящей о том, что внутри my_fun_wrapper символ Zmy_fundd не распознается. Получив такую ​​ошибку, я подозревал, что в процессе компоновки что-то пошло не так. Но как ни странно, как я уже сказал, компилятор не выдал никакой ошибки. Тем не менее, более тщательная проверка подробного вывода компилятора показала, что mkoctfile автоматически меняет компилятор между различными файлами в зависимости от их расширения. Таким образом, my_fun_wrapper.cpp компилируется с помощью g++ -std=gnu++11, а custom_function_libc.c компилируется с помощью gcc -std=gnu11, и каким-то образом файл custom_function_libc.o, полученный в результате этого процесса компиляции, когда связанный с my_fun_wrapper.o не соответствует неразрешенным символам.

Пример выше очень упрощен. На практике в моем случае custom_function_libc включает в себя гораздо больше пользовательских библиотек C. Обходной путь до сих пор заключался в клонировании исходного файла .c для этих библиотек в файлы .cpp. Но мне не очень нравится это решение.

Как в конечном итоге можно безопасно смешать C++ и C код и успешно скомпилировать его с помощью mkoctfile? Руководство octave предлагает добавить extern C спецификацию (см. здесь ), с которой, я боюсь, я не очень знаком. Это лучший способ? Не могли бы вы предложить мне альтернативное, потенциальное альтернативное решение?

1 Ответ

0 голосов
/ 15 января 2019

Так что, по-видимому, самое простое решение, согласно моему вышеприведенному сообщению, - исправить оболочку следующими директивами препроцессора:

// my_fun_wrapper.cpp

#include <octave/oct.h>

// ADDED code to include the C source code
#ifdef __cplusplus
extern "C"
{
#endif
// END ADDITION
#include "custom_functions_libc.h"
// ADDED code to include the C source code
#ifdef __cplusplus
}  /* end extern "C" */
#endif
// END ADDITION

...
...

Это скомпилирует и скомпонует нормально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...