Build 32-bit DLL on 64-bit Windows® Platform Using MSVC Toolchain
Note: To simply produce a 32-bit DLL on Windows® with Microsoft® Visual Studio installed, use a CMake toolchain like Microsoft Visual Studio Project 2017 | CMake (32-bit Windows)
. This page documents how you can author a custom toolchain to change compiler options and integrate new compilers. For more information on building generated code with CMake, see Configure CMake Build Process.
Register and use a Microsoft® Visual C/C++ (MSVC) toolchain running on a 64-bit Windows® platform to compile a 32-bit dynamic link library (DLL). This example uses a Microsoft® compiler. However, the concepts and programming interface apply for other toolchains. Once you register the toolchain, you can select it from a list of toolchains, and the code generator generates a makefile to build the code by using that toolchain. A toolchain consists of several tools, such as a compiler, linker, and archiver with multiple different configuration options. The toolchain compiles, links, and runs code on a specified platform. To access the files that this example uses, click Open Script.
Check Platform and Determine MSVC Version
This code checks that the platform is supported and that you have a supported version of Microsoft® Visual C/C++. The my_msvc_32bit_tc.m
toolchain definition can use the Microsoft® Visual Studio versions 9.0, 10.0, 11.0, 12.0, 14.0, or 15.0.
If you are not using a Windows® platform, or if you do not have a supported version of Microsoft® Visual C/C++, the example generates only code and a makefile, without running the generated makefile.
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
Function for the Dynamic Link Library
The example function for the dynamic link library, myMatlabFunction.m
, multiplies a number by two.
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);
Create and Configure an MSVC Toolchain
The my_msvc_32bit_tc.m
toolchain definition function takes in an argument containing the Visual Studio version number. In this example, the commands that create and configure this toolchain are:
tc = my_msvc_32bit_tc(VersionNumbers{end}); save my_msvc_32bit_tc tc;
Executing "C:\Users\mamlicke\OneDrive - MathWorks\Documents\MATLAB\ExampleManager\mamlicke.Bdoc24a.j2373701\coder-ex19875030\my_msvc_32bit_tc"... Executed "C:\Users\mamlicke\OneDrive - MathWorks\Documents\MATLAB\ExampleManager\mamlicke.Bdoc24a.j2373701\coder-ex19875030\my_msvc_32bit_tc".
Register the Toolchain
Before the code generator can use a toolchain for the build process, the RTW.TargetRegistry
must contain the toolchain registration. This registration can come from any rtwTargetInfo.m
file on the MATLAB path. MATLAB will load a new registration if the RTW.TargetRegistry
is reset.
Create the rtwTargetInfo.m
file from the corresponding text file myRtwTargetInfo.txt
.
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');
Create Code Generation Configuration Object
To generate the 32-bit dynamic link library (DLL), create a 'dll'
code generation configuration object. Specifying 'dll'
directs the linker (a build tool in the toolchain) to use "Shared Library" linker commands.
cfg = coder.config('dll');
Configure Code Generation for 32-bit Hardware
To successfully generate code that is compatible with 32-bit hardware, the generated code must use the correct underlying C types (for example, int
, signed char
, and others). These types are the basis for typedef
statements for sized types (for example, uint8
, int16
, and others). Set the configuration with the command:
cfg.HardwareImplementation.ProdHWDeviceType = ... 'Generic->Unspecified (assume 32-bit Generic)';
Configure Code Generation to Use the 32-bit Toolchain
Set the name of the Toolchain
property to match the Name
that you specify in the rtwTargetInfo.m
file.
cfg.Toolchain = ... 'Microsoft 32 Bit Toolchain | nmake makefile (64-bit Windows)';
Select Verbose Status Reporting
To provide confirmation of compiler flags that the toolchain uses to build the DLL, select verbose status reporting.
cfg.Verbose = true;
Determine Whether to Generate Code Only
When the Microsoft® compilers are not installed, the code generator generates only code and the makefile. When the supported compilers are installed, the code generator builds the 32-bit binary file.
if supportedCompilerInstalled cfg.GenCodeOnly = false; else cfg.GenCodeOnly = true; end
Generate Code and Build a DLL
To use the toolchain for code generation and build the DLL (if build is enabled), at the command prompt, enter:
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.Bdoc24a.j2373701\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.11.7 ** Copyright (c) 2021 Microsoft Corporation ********************************************************************** [vcvarsall.bat] Environment initialized for: 'x64_x86' Microsoft (R) Program Maintenance Utility Version 14.29.30137.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\MAMLIC~2.J23\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\MAMLIC~2.J23\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\MAMLIC~2.J23\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.
Build and Run an Executable
If you have a supported version of the compiler installed, you can build the 32-bit executable by using a C main function. You can use the executable to test that the generated code works as expected.
cfge = coder.config('exe'); cfge.CustomInclude = {pwd}; 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.Bdoc24a.j2373701\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.11.7 ** Copyright (c) 2021 Microsoft Corporation ********************************************************************** [vcvarsall.bat] Environment initialized for: 'x64_x86' Microsoft (R) Program Maintenance Utility Version 14.29.30137.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\MAMLIC~2.J23\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\MAMLIC~2.J23\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\MAMLIC~2.J23\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\MAMLIC~2.J23\CODER-~1\codegen\exe\myMatlabFunction\myMatlabFunction.c" myMatlabFunction.c ### Creating standalone executable "C:\Users\mamlicke\ONEDRI~1\DOCUME~1\MATLAB\EXAMPL~1\MAMLIC~2.J23\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\MAMLIC~2.J23\CODER-~1\myMatlabFunction.exe @myMatlabFunction_rtw.rsp ### Created: C:\Users\mamlicke\ONEDRI~1\DOCUME~1\MATLAB\EXAMPL~1\MAMLIC~2.J23\CODER-~1\myMatlabFunction.exe ### Successfully generated all binary outputs. ------------------------------------------------------------------------ Code generation successful. myMatlabFunction(3.1416) = 6.2832
Optional Step: Unregister the toolchain
To unregister the toolchain, enter:
delete ./rtwTargetInfo.m RTW.TargetRegistry.getInstance('reset');