我当前的MEX文件编译正确,但是,我想创建几个MEX文件:
- mex_a.cpp
- mex_b.cpp
- mex_c.cpp
此时,mex_a.cpp包含典型的函数定义:
class MexFunction : public matlab::mex::Function {
private:
// Get pointer to engine
std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();
// Get array factory
std::shared_ptr<matlab::data::ArrayFactory> factoryPtr;
private:
void operator()(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs) override
{
try
{
// Parse inputs..
mex_aux->mex_common_function(...)
// Parse outputs..
}
catch (int)
{
std::fprintf(stdout, "ERROR: Something unexpected happened...");
}
}
字符串
在mex_aux
中,我们可以找到mex_common_function
的定义和实现。该对象的目的是供mex_a.cpp、mex_b.cpp和mex_c.cpp使用,基本上与普通库的功能相同。
我的发现是:
- 如果mex_common_function是静态的,则一切正常。
- 否则,它在使用matlab对象时不起作用。
该.hpp文件如下所示:
#pragma once
// Include system libraries
# include <string>
# include <utility>
// MATLAB stuff
#include "mex.hpp"
class mex_aux
{
public:
// Constructor
mex_aux() = default;
// Destructor
~mex_aux() = default;
private:
// Get pointer to engine
std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr;
// Get array factory
std::shared_ptr<matlab::data::ArrayFactory> factoryPtr;
public:
// Setters:
void set_matlab_ptr(std::shared_ptr<matlab::engine::MATLABEngine>& matlab_ptr) {this->matlabPtr = matlab_ptr; }
void set_factory_ptr(std::shared_ptr<matlab::data::ArrayFactory>& factory_ptr) {this->factoryPtr = factory_ptr; }
public:
// The used function, if this one is set as static (hence not using members of the class) it works.
void mex_common_function();
型
我现在所做的,因此在MATLAB中得到以下错误(不是在构建时):
- 正在将
matlabPtr
设置为mex_aux
中的内部指针。 - 对于
factoryPtr
也是如此。
这两个都是从主mex函数文件(即mex_a.cpp)中构建mex_aux
后,使用的setters。
MATLAB中的错误:
Invalid MEX-file
'/path/to/mex/mexfunction.mexa64':
/path/to/external/libextern.so:
undefined symbol:
_ZN6matlab6engine12MATLABEngine5fevalERKNSt7__cxx1112basic_stringIDsSt11char_traitsIDsESaIDsEEEiRKSt6vectorINS_4data5ArrayESaISC_EERKSt10shared_ptrISt15basic_streambufIDsS5_EESM_
Error in mex_vsod (line 50)
b(:,:,i) = mexfunction(...);
型
我的CMakeLists.txt:
# MEX AUX Library
set(LIBRARY_MEX_AUX "mex_aux")
add_library(${LIBRARY_MEX_AUX} SHARED
src/core/tools/mex_aux.cpp)
target_link_libraries(${LIBRARY_MEX_AUX}
${Matlab_MEX_LIBRARY}
${Matlab_MX_LIBRARY})
set_target_properties(${LIBRARY_MEX_AUX} PROPERTIES
COMPILE_FLAGS "-fPIC"
LINK_FLAGS "-Wl,-rpath,./") # To use relative paths in shared libs
# MEX FILES
if (BUILD_WITH_MATLAB)
# MEX functions files
matlab_add_mex(NAME mex_vsaod
SRC src/main/mex_cpp/mex_a.cpp
LINK_TO ${LIBRARY_target1} ... ${LIBRARY_targetN} ${LIBRARY_MEX_AUX})
endif ()
型
我猜内存中发生了一些错误,因为mex_aux
的指针可能指向内存中无法访问的位置(仅限于mex文件-mex_a.cpp?-)...
谁能给予我点提示吗?我会很感激的。
1条答案
按热度按时间hlswsv351#
我在MEX文件中使用了一个共享库,其中多个MEX文件需要访问同一个C对象。然后在共享库中创建对象,并可以在链接到它的所有MEX文件中使用它。
但是如果共享库需要调用MATLAB函数,那么构建起来就变得复杂得多。
考虑到你的用例,“* 它们主要是转换函数,比如
std::vector<doubles>
到matlab::arrays
*",我会把它做成一个只有头文件的库或静态库。你不需要在MEX文件中共享一个C对象,你不需要把它变成一个共享库。而且转换函数通常不会很大,通过静态链接MEX文件而不必要地使MEX文件膨胀的复杂代码。但是,如果你真的想构建一个调用MATLAB的共享库,那么你需要像构建MEX文件一样构建它,除了它没有标准的MEX文件入口点或MEX文件扩展名。但是你确实需要链接所有相同的MATLAB库,并设置所有相同的预处理器定义。
当你在CMake文件中调用
matlab_add_mex
时,你会运行这个CMake代码。这显示了构建MEX文件的复杂性。如果你想编写一个适用于所有版本的MATLAB和所有平台的CMake脚本,你基本上必须复制该函数的大部分功能。但是你使用的是C++ API,因此,仅遵循适用于MATLAB 9.4(R2018 a)及更新版本的路径。这包括设置Matlab_HAS_CPP_API
和Matlab_DATAARRAY_LIBRARY
时运行的所有位。它看起来像这样(未经测试!):
字符串
请注意,这段代码可能会在MATLAB的未来版本中发生变化,它们会不断改变构建MEX文件的方式。因此,静态链接转换函数确实要方便得多。
在构建
SHARED
库时,您添加的-fPIC
选项已经由CMake处理。但是您必须显式地将其添加到您打算链接到共享库的静态库中,至少在Linux上是这样。