使用 MATLAB 引擎连接到 运行 个 MATLAB

Connect to already running MATLAB with MATLAB Engine

The MATLAB Engine API allows accessing MATLAB functionality from a C program. To set up a MATLAB Engine session, one calls the engOpen 函数。默认情况下,这会启动一个新的 MATLAB 实例,专供引擎应用程序使用。

我想要的是使用引擎应用程序中的已经运行宁 MATLAB 会话,这样我就可以访问它的变量。 我需要在 Linux 和 OS X 上执行此操作。

Engine 接口在 Windows(它使用 COM 服务器)和 Unix 上有非常不同的实现。在 Unix 上,我们必须将 MATLAB 可执行文件的位置传递给 engOpen,而在 Windows(引擎使用 COM 服务器)上我们不需要。在 Windows 上, 可以将现有的 MATLAB 实例用于引擎应用程序:只需 运行 enableservice('AutomationServer', true)。 Unix系统有解决方案吗?

我希望有一个通用的解决方案——也许没有记录——因为,based on the documentation, the Python interface seems to allow this. I tested this on OS X and it works. I can, for example, start up an interactive MATLAB session, set a variable a=5, then start Python, connect to the same session and be able to retrieve this variable. It is also possible to connect to an already running session from Java.

但是我需要从 C 中执行此操作,而不是从 Python 中执行此操作,因为它将在 MATLink 中使用 Mathematica-MATLink 接口。 Python 接口是如何做到这一点的?我如何使用 C 重现相同的内容?

如果有一个替代 C API 而不是 "MATLAB Engine" 使这成为可能(可能是 Python 接口所基于的其他一些已记录或未记录的 C API上),我可以接受它作为答案。我想要一个可以利用已经 运行ning interactive MATLAB 会话的 C 程序。


更新:

一些人在 Python 界面中四处寻找,发现它使用了一个名为 libmwengine_api 的库。这与记录的 MATLAB Engine C API 不同。我们可以看看这个库中的符号。在 OS X 上,

nm -g libmwengine_api.dylib | c++filt

然后我们可以 google 获取这些符号或 grep MATLAB 安装目录以查找包含它们的文件。纯文本中没有任何内容出现。

基于此,我认为 Python 接口使用了一个未记录的 C++ 引擎 API,它与旧的、有记录的 C 引擎不同。

"On the Mac and Linux® platforms, you cannot make an engine program connect to an existing MATLAB session."

这是它的出处Python Implementation,看看对你有没有帮助。

一些搜索给我的印象是 libmwengine 是嵌入式系统中使用的库的一部分,并且早已过时。

参见 This link ,库 libmwengine_api 已废弃很久 back.Maybe 这就是它未被记录的原因。

我能够在 MacOS 的命令行中连接到一个已经 运行ning 的 MATLAB 会话(应该可以在任何 Linux 上工作)。我还没有弄清楚如何从 MATLAB IDE 连接到已经 运行ning MATLAB 会话 ,但我个人的动机是不必使用IDE。我无限期地在后台保留一个 MATLAB 内核 运行ning 并根据需要连接到它。这允许我从我的文本编辑器以批处理模式 运行 MATLAB 脚本,而不必每次都启动一个新内核。

这是我的做法。如果您需要更多详细信息,我很乐意提供完成它的完整脚本:

1。 从 Python 启动 MATLAB kernel/session。我没有使用我发现难以使用的 MATLAB 引擎 API,而是选择了一个名为 imatlab 的现有 iPython Jupyter 内核接口。我必须安装这个 (pip install imatlab) 以及 Jupyter (pip install jupyter):

from notebook.services.kernels.kernelmanager import MappingKernelManager
m = MappingKernelManager()
m.start_kernel(kernel_name="imatlab")
...

这会在工作目录中创建一个名为 kernel-kernel_id.json.json "connection file",其中 kernel_id 一个 UID(例如 4931ac70-e8fd-4d35-81b2-de53e07956c8)。我还将这个内核的名称写入我的 Python 脚本中的文件:

id = m.list_kernel_ids()[0]
text_file = open("/Users/Zach/.matlab_kernel/matlab_kernel_name.txt", "w")
text_file.write(id)
text_file.close()

我实际上是在后台 TMUX 会话中执行此操作,因此我不必让我的终端 window 打开。也很高兴对此发表评论。

2。 使用 Jupyter 的 console 接口连接到这个 MATLAB 内核(尽管我也可以连接一个连接到这个内核的 Jupyter notebook)。首先,我必须从我写入的文件中检索 kernel_name

MATLABKERNELNAME=`cat /Users/Zach/.matlab_kernel/matlab_kernel_name.txt`
cd /Users/Zach/.matlab_kernel
jupyter console --existing $MATLABKERNELNAME

我还制作了这个 bash 命令的变体,它打开内核并发送命令以获取 MATLAB .m 文件:

mtlb_existing_run_expect(){
        thefilename=`to_abs_path `
        thecurrentdirectory=`pwd`
        thekernelname=`cat /Users/Zach/.matlab_kernel/matlab_kernel_name.txt`
        expect <(cat <<EOF
            cd /Users/zach/.matlab_kernel
            spawn jupyter console --existing $thekernelname --simple-prompt --no-confirm-exit && exit
            expect ": "
            send "cd '$thecurrentdirectory'\n"
            expect ": "
            send "run('$thefilename')\n"
            interact -u "exp0"
EOF
)
}

您会注意到我总是 cd 进入我启动内核的目录。那是因为 Jupyter 在那里创建了 .json "connection file",如果你在目录中,它会自动读取它,并将内核 UID 作为 --existing 标志的参数。

希望对大家有所帮助!