Main Content

本页翻译不是最新的。点击此处可查看最新英文版本。

使用 MSVC 工具链在 64 位 Windows® 平台上编译 32 位 DLL

注意:如果只需要在安装了 Microsoft® Visual Studio 的 Windows® 上生成 32 位 DLL,请使用 CMake 工具链,如 Microsoft Visual Studio Project 2017 | CMake (32-bit Windows)。本页说明如何创建自定义工具链来更改编译器选项和集成新编译器。有关使用 CMake 编译所生成代码的详细信息,请参阅Configure CMake Build Process

注册并使用运行在 64 位 Windows® 平台上的 Microsoft®Visual C/C++(MSVC) 工具链,编译 32 位动态链接库 (DLL)。此示例使用 Microsoft® 编译器。然而,概念和编程接口适用于其他工具链。一旦注册工具链,就可以从工具链列表中选择它,代码生成器会生成联编文件来使用该工具链编译代码。工具链由几个工具组成,如编译器、链接器和具有多个不同配置选项的存档器。工具链在指定的平台上编译、链接和运行代码。要访问此示例使用的文件,请点击打开脚本

检查平台并确定 MSVC 版本

以下代码检查平台是否受支持,以及您是否有受支持的 Microsoft® Visual C/C++ 版本。my_msvc_32bit_tc.m 工具链定义可以使用 Microsoft®Visual Studio 版本 9.0、10.0、11.0、12.0、14.0 或 15.0。

如果您没有使用 Windows® 平台,或如果您没有支持的 Microsoft®Visual C/C++ 版本,该示例仅生成代码和联编文件,而不运行生成的联编文件。

VersionNumbers = {'14.0'}; % Placeholder value
if ~ispc
    supportedCompilerInstalled = false;
else
    installed_compilers = mex.getCompilerConfigurations('C', 'Installed');
    MSVC_InstalledVersions = regexp({installed_compilers.Name}, 'Microsoft Visual C\+\+ 20\d\d');
    MSVC_InstalledVersions = cellfun(@(a)~isempty(a), MSVC_InstalledVersions);
    if ~any(MSVC_InstalledVersions)
        supportedCompilerInstalled = false;
    else
        VersionNumbers = {installed_compilers(MSVC_InstalledVersions).Version}';
        supportedCompilerInstalled = true;
    end
end

动态链接库的函数

动态链接库的示例函数 myMatlabFunction.m 将数字乘以 2。

function y = myMatlabFunction(u) 
% myMatlabFunction: Returns twice its input.
% Copyright 2017 The MathWorks, Inc.

%#codegen
assert(isa(u, 'double'), 'The input must be a "double".');
assert(all([1, 1] == size( u )), 'The input must be a scalar.');

y = double(u + u);

创建和配置 MSVC 工具链

my_msvc_32bit_tc.m 工具链定义函数接受包含 Visual Studio 版本号的参数。在此示例中,创建和配置该工具链的命令是:

tc = my_msvc_32bit_tc(VersionNumbers{end});
save my_msvc_32bit_tc tc;
Executing "C:\Users\mamlicke\OneDrive - MathWorks\Documents\MATLAB\ExampleManager\mamlicke.Bdoc23b.j2327073.1\coder-ex19875030\my_msvc_32bit_tc"...
Executed "C:\Users\mamlicke\OneDrive - MathWorks\Documents\MATLAB\ExampleManager\mamlicke.Bdoc23b.j2327073.1\coder-ex19875030\my_msvc_32bit_tc".

注册工具链

在代码生成器可以将工具链用于编译过程之前,RTW.TargetRegistry 必须包含工具链注册。此注册可以来自 MATLAB 路径中的任何 rtwTargetInfo.m 文件。如果重置 RTW.TargetRegistry,MATLAB 将加载新注册。

从对应的文本文件 myRtwTargetInfo.txt 创建 rtwTargetInfo.m 文件。

function myRtwTargetInfo(tr)
%RTWTARGETINFO Registration file for custom toolchains.

% Copyright 2012-2017 The MathWorks, Inc.

tr.registerTargetInfo(@createToolchainRegistryFor32BitMSVCToolchain);

end

% -------------------------------------------------------------------------
% Create the ToolchainInfoRegistry entries
% -------------------------------------------------------------------------
function config = createToolchainRegistryFor32BitMSVCToolchain

config(1)                       = coder.make.ToolchainInfoRegistry;
config(1).Name                  = 'Microsoft 32 Bit Toolchain | nmake makefile (64-bit Windows)';
config(1).FileName              = fullfile(fileparts(mfilename('fullpath')), 'my_msvc_32bit_tc.mat');
config(1).TargetHWDeviceType    = {'Intel->x86-32 (Windows32)','AMD->x86-32 (Windows32)','Generic->Unspecified (assume 32-bit Generic)'};
config(1).Platform              =  {'win64'};

end
copyfile myRtwTargetInfo.txt rtwTargetInfo.m
RTW.TargetRegistry.getInstance('reset');

创建代码生成配置对象

要生成 32 位动态链接库 (DLL),请创建一个 'dll' 代码生成配置对象。指定 'dll' 会指示链接器(工具链中的一个编译工具)使用“共享库”链接器命令。

cfg = coder.config('dll');

为 32 位硬件配置代码生成

要成功生成与 32 位硬件兼容的代码,生成的代码必须使用正确的底层 C 类型(例如,intsigned char 等)。这些类型是大小类型的 typedef 语句的基础(例如,uint8int16 等)。使用以下命令设置配置:

cfg.HardwareImplementation.ProdHWDeviceType = ...
    'Generic->Unspecified (assume 32-bit Generic)';

将代码生成配置为使用 32 位工具链

设置 Toolchain 属性的名称,以匹配您在 rtwTargetInfo.m 文件中指定的 Name

cfg.Toolchain = ...
    'Microsoft 32 Bit Toolchain | nmake makefile (64-bit Windows)';

选择详尽状态报告

要确认工具链用于构建 DLL 的编译器标志,请选择详尽状态报告。

cfg.Verbose = true;

确定是否仅生成代码

当没有安装 Microsoft® 编译器时,代码生成器只生成代码和联编文件。安装支持的编译器后,代码生成器会构建 32 位二进制文件。

if supportedCompilerInstalled
    cfg.GenCodeOnly = false;
else
    cfg.GenCodeOnly = true;
end

生成代码并编译 DLL

要使用工具链生成代码并编译 DLL(如果已启用编译),请在命令提示符下输入:

codegen -config cfg myMatlabFunction -args { double(1.0) };
### Compiling function(s) myMatlabFunction ...
------------------------------------------------------------------------
### Using toolchain: Microsoft 32 Bit Toolchain | nmake makefile (64-bit Windows)
### 'C:\Users\mamlicke\OneDrive - MathWorks\Documents\MATLAB\ExampleManager\mamlicke.Bdoc23b.j2327073.1\coder-ex19875030\codegen\dll\myMatlabFunction\myMatlabFunction_rtw.mk' is up to date
### Building 'myMatlabFunction': nmake  -f myMatlabFunction_rtw.mk all
**********************************************************************
** Visual Studio 2019 Developer Command Prompt v16.7.7
** Copyright (c) 2020 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64_x86'

Microsoft (R) Program Maintenance Utility Version 14.27.29112.0
Copyright (C) Microsoft Corporation.  All rights reserved.

	cl  -c -nologo -GS -W4 -DWIN32 -D_MT -MTd -D_CRT_SECURE_NO_WARNINGS  /O2 /Oy-  -DMODEL=myMatlabFunction @myMatlabFunction_rtw_comp.rsp -Fo"myMatlabFunction_initialize.obj" "C:\Users\mamlicke\ONEDRI~1\DOCUME~1\MATLAB\EXAMPL~1\MA98F7~1.1\CODER-~1\codegen\dll\myMatlabFunction\myMatlabFunction_initialize.c"
myMatlabFunction_initialize.c
	cl  -c -nologo -GS -W4 -DWIN32 -D_MT -MTd -D_CRT_SECURE_NO_WARNINGS  /O2 /Oy-  -DMODEL=myMatlabFunction @myMatlabFunction_rtw_comp.rsp -Fo"myMatlabFunction_terminate.obj" "C:\Users\mamlicke\ONEDRI~1\DOCUME~1\MATLAB\EXAMPL~1\MA98F7~1.1\CODER-~1\codegen\dll\myMatlabFunction\myMatlabFunction_terminate.c"
myMatlabFunction_terminate.c
	cl  -c -nologo -GS -W4 -DWIN32 -D_MT -MTd -D_CRT_SECURE_NO_WARNINGS  /O2 /Oy-  -DMODEL=myMatlabFunction @myMatlabFunction_rtw_comp.rsp -Fo"myMatlabFunction.obj" "C:\Users\mamlicke\ONEDRI~1\DOCUME~1\MATLAB\EXAMPL~1\MA98F7~1.1\CODER-~1\codegen\dll\myMatlabFunction\myMatlabFunction.c"
myMatlabFunction.c
### Creating dynamic library ".\myMatlabFunction.dll" ...
	link /MACHINE:X86 /DEBUG /DEBUGTYPE:cv  /INCREMENTAL:NO /NOLOGO kernel32.lib ws2_32.lib mswsock.lib advapi32.lib  -dll -def:myMatlabFunction.def -out:.\myMatlabFunction.dll @myMatlabFunction_rtw.rsp  
   Creating library .\myMatlabFunction.lib and object .\myMatlabFunction.exp
### Created: .\myMatlabFunction.dll
### Successfully generated all binary outputs.


------------------------------------------------------------------------
Code generation successful.

编译并运行可执行文件

如果您安装支持的编译器版本,您可以通过使用 C 主函数来构建 32 位可执行文件。您可以使用可执行文件来测试生成的代码是否按预期工作。

cfge = coder.config('exe');
cfge.CustomInclude = split(pwd, filesep);
cfge.CustomSource = 'myMatlabFunction_main.c';
cfge.GenCodeOnly = cfg.GenCodeOnly;
cfge.Verbose = true;
cfge.Toolchain = ...
    'Microsoft 32 Bit Toolchain | nmake makefile (64-bit Windows)';
codegen -config cfge myMatlabFunction -args { double(1.0) };
if supportedCompilerInstalled
    pause(5); %wait for EXE to get generated
    system('myMatlabFunction 3.1416'); % Expected output: myMatlabFunction(3.1416) = 6.2832
end
### Compiling function(s) myMatlabFunction ...
------------------------------------------------------------------------
### Using toolchain: Microsoft 32 Bit Toolchain | nmake makefile (64-bit Windows)
### 'C:\Users\mamlicke\OneDrive - MathWorks\Documents\MATLAB\ExampleManager\mamlicke.Bdoc23b.j2327073.1\coder-ex19875030\codegen\exe\myMatlabFunction\myMatlabFunction_rtw.mk' is up to date
### Building 'myMatlabFunction': nmake  -f myMatlabFunction_rtw.mk all
**********************************************************************
** Visual Studio 2019 Developer Command Prompt v16.7.7
** Copyright (c) 2020 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64_x86'

Microsoft (R) Program Maintenance Utility Version 14.27.29112.0
Copyright (C) Microsoft Corporation.  All rights reserved.

	cl  -c -nologo -GS -W4 -DWIN32 -D_MT -MTd -D_CRT_SECURE_NO_WARNINGS  /O2 /Oy-  -DMODEL=myMatlabFunction @myMatlabFunction_rtw_comp.rsp -Fo"myMatlabFunction_main.obj" "C:\Users\mamlicke\ONEDRI~1\DOCUME~1\MATLAB\EXAMPL~1\MA98F7~1.1\CODER-~1\myMatlabFunction_main.c"
myMatlabFunction_main.c
	cl  -c -nologo -GS -W4 -DWIN32 -D_MT -MTd -D_CRT_SECURE_NO_WARNINGS  /O2 /Oy-  -DMODEL=myMatlabFunction @myMatlabFunction_rtw_comp.rsp -Fo"myMatlabFunction_initialize.obj" "C:\Users\mamlicke\ONEDRI~1\DOCUME~1\MATLAB\EXAMPL~1\MA98F7~1.1\CODER-~1\codegen\exe\myMatlabFunction\myMatlabFunction_initialize.c"
myMatlabFunction_initialize.c
	cl  -c -nologo -GS -W4 -DWIN32 -D_MT -MTd -D_CRT_SECURE_NO_WARNINGS  /O2 /Oy-  -DMODEL=myMatlabFunction @myMatlabFunction_rtw_comp.rsp -Fo"myMatlabFunction_terminate.obj" "C:\Users\mamlicke\ONEDRI~1\DOCUME~1\MATLAB\EXAMPL~1\MA98F7~1.1\CODER-~1\codegen\exe\myMatlabFunction\myMatlabFunction_terminate.c"
myMatlabFunction_terminate.c
	cl  -c -nologo -GS -W4 -DWIN32 -D_MT -MTd -D_CRT_SECURE_NO_WARNINGS  /O2 /Oy-  -DMODEL=myMatlabFunction @myMatlabFunction_rtw_comp.rsp -Fo"myMatlabFunction.obj" "C:\Users\mamlicke\ONEDRI~1\DOCUME~1\MATLAB\EXAMPL~1\MA98F7~1.1\CODER-~1\codegen\exe\myMatlabFunction\myMatlabFunction.c"
myMatlabFunction.c
### Creating standalone executable "C:\Users\mamlicke\ONEDRI~1\DOCUME~1\MATLAB\EXAMPL~1\MA98F7~1.1\CODER-~1\myMatlabFunction.exe" ...
	link /MACHINE:X86 /DEBUG /DEBUGTYPE:cv  /INCREMENTAL:NO /NOLOGO kernel32.lib ws2_32.lib mswsock.lib advapi32.lib -out:C:\Users\mamlicke\ONEDRI~1\DOCUME~1\MATLAB\EXAMPL~1\MA98F7~1.1\CODER-~1\myMatlabFunction.exe @myMatlabFunction_rtw.rsp  
### Created: C:\Users\mamlicke\ONEDRI~1\DOCUME~1\MATLAB\EXAMPL~1\MA98F7~1.1\CODER-~1\myMatlabFunction.exe
### Successfully generated all binary outputs.


------------------------------------------------------------------------
Code generation successful.

myMatlabFunction(3.1416) = 6.2832 

可选步骤:注销工具链

要注销工具链,请输入:

delete ./rtwTargetInfo.m
RTW.TargetRegistry.getInstance('reset');

相关主题