Создайте 32-битный DLL на 64-битной платформе Windows® Используя набор инструментальных средств MSVC

Укажите и используйте Microsoft® Visual C/C ++ (MSVC) набор инструментальных средств, работающий на 64-битной платформе Windows®, чтобы скомпилировать 32-битную динамически подключаемую библиотеку (DLL). Этот пример использует компилятор Microsoft®. Однако концепции и интерфейс программирования применяются к другим наборам инструментальных средств. Если вы указываете набор инструментальных средств, можно выбрать его из списка наборов инструментальных средств, и генератор кода генерирует make-файл, чтобы создать код при помощи того набора инструментальных средств. Набор инструментальных средств состоит из нескольких инструментов, таких как компилятор, компоновщик и archiver с несколькими различными параметрами конфигурации. Компиляции набора инструментальных средств, ссылки и код выполнений по заданной платформе. Чтобы получить доступ к файлам, которые использует этот пример, нажмите Open Script.

Проверяйте платформу и определите версию MSVC

Этот код проверяет, что платформа поддерживается и что у вас есть поддерживаемая версия Microsoft® Visual C/C ++. Определение набора инструментальных средств my_msvc_32bit_tc.m может использовать версии 9.0, 10.0, 11.0, 12.0, 14.0 Visual Studio Microsoft®, или 15.0.

Если вы не используете платформу Windows®, или если у вас нет поддерживаемой версии Microsoft® Visual C/C ++, пример генерирует только код и make-файл, не запуская сгенерированный make-файл.

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, умножает номер на два.

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 "H:\Examples\coder-ex19875030\my_msvc_32bit_tc"...
Executed "H:\Examples\coder-ex19875030\my_msvc_32bit_tc".

Укажите набор инструментальных средств

Прежде чем генератор кода может использовать набор инструментальных средств для процесса сборки, RTW.TargetRegistry должен содержать регистрацию набора инструментальных средств. Эта регистрация может прибыть из любого файла rtwTargetInfo.m на пути MATLAB. MATLAB загрузит новую регистрацию, если RTW.TargetRegistry будет сброшен.

Создайте файл rtwTargetInfo.m из соответствующего текстового файла 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');

Создайте объект настройки генерации кода

Чтобы сгенерировать 32-битную динамически подключаемую библиотеку (DLL), создайте объект настройки генерации кода 'dll'. Определение 'dll' направляет компоновщика (инструмент сборки в наборе инструментальных средств), чтобы пользоваться "Разделяемой Библиотекой" команды компоновщика.

cfg = coder.config('dll');

Сконфигурируйте генерацию кода для 32-битного оборудования

Чтобы успешно сгенерировать код, который совместим с 32-битным оборудованием, сгенерированный код должен использовать правильные базовые типы C (например, int, signed char и другие). Эти типы являются основанием для операторов typedef для размерных типов (например, uint8, int16 и другие). Установите настройку с командой:

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

Сконфигурируйте генерацию кода, чтобы использовать 32-битный набор инструментальных средств

Определите имя свойства Toolchain совпадать с Name, который вы задаете в файле rtwTargetInfo.m.

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

Выберите Verbose Status Reporting

Чтобы обеспечить подтверждение флагов компилятора что использование набора инструментальных средств, чтобы создать DLL, выберите многословное создание отчетов о состоянии.

cfg.Verbose = true;

Определите, сгенерировать ли код только

Когда компиляторы Microsoft® не установлены, генератор кода генерирует только код и make-файл. Когда поддерживаемые компиляторы установлены, генератор кода создает 32-битный двоичный файл.

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

Сгенерируйте код и создайте DLL

Использовать набор инструментальных средств для генерации кода и создавать DLL (если сборка включена), в командной строке, введите:

codegen -config cfg myMatlabFunction -args { double(1.0) };
### Using toolchain: Microsoft 32 Bit Toolchain | nmake makefile (64-bit Windows)
### Creating 'H:\Examples\coder-ex19875030\codegen\dll\myMatlabFunction\myMatlabFunction_rtw.mk' ...
### Building 'myMatlabFunction': nmake  -f myMatlabFunction_rtw.mk all
 
H:\Examples\coder-ex19875030\codegen\dll\myMatlabFunction>set "VSCMD_START_DIR=H:\Examples\coder-ex19875030\codegen\dll\myMatlabFunction"  
 
H:\Examples\coder-ex19875030\codegen\dll\myMatlabFunction>call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\\VC\Auxiliary\Build\vcvarsall.bat" amd64_x86  
********************************************************************** 
** Visual Studio 2017 Developer Command Prompt v15.0.26730.12 
** Copyright (c) 2017 Microsoft Corporation 
********************************************************************** 
[vcvarsall.bat] Environment initialized for: 'x64_x86' 
 
Microsoft (R) Program Maintenance Utility Version 14.11.25507.1 
Copyright (C) Microsoft Corporation.  All rights reserved. 
 
	cl  -c -nologo -GS -W4 -DWIN32 -D_MT -MTd -D_CRT_SECURE_NO_WARNINGS  /Od /Oy-  -DMODEL=myMatlabFunction -DHAVESTDIO -DUSE_RTMODEL @myMatlabFunction_rtw_comp.rsp -Fo"myMatlabFunction_initialize.obj" "H:\Examples\coder-ex19875030\codegen\dll\myMatlabFunction\myMatlabFunction_initialize.c" 
myMatlabFunction_initialize.c 
	cl  -c -nologo -GS -W4 -DWIN32 -D_MT -MTd -D_CRT_SECURE_NO_WARNINGS  /Od /Oy-  -DMODEL=myMatlabFunction -DHAVESTDIO -DUSE_RTMODEL @myMatlabFunction_rtw_comp.rsp -Fo"myMatlabFunction_terminate.obj" "H:\Examples\coder-ex19875030\codegen\dll\myMatlabFunction\myMatlabFunction_terminate.c" 
myMatlabFunction_terminate.c 
	cl  -c -nologo -GS -W4 -DWIN32 -D_MT -MTd -D_CRT_SECURE_NO_WARNINGS  /Od /Oy-  -DMODEL=myMatlabFunction -DHAVESTDIO -DUSE_RTMODEL @myMatlabFunction_rtw_comp.rsp -Fo"myMatlabFunction.obj" "H:\Examples\coder-ex19875030\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. 

Создание и запуск исполняемого файла

Если у вас есть поддерживаемая версия установленного компилятора, можно создать 32-битный исполняемый файл при помощи основной функции C. Можно использовать исполняемый файл, чтобы протестировать это, сгенерированный код работает как ожидалось.

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
### Using toolchain: Microsoft 32 Bit Toolchain | nmake makefile (64-bit Windows)
### Creating 'H:\Examples\coder-ex19875030\codegen\exe\myMatlabFunction\myMatlabFunction_rtw.mk' ...
### Building 'myMatlabFunction': nmake  -f myMatlabFunction_rtw.mk all
 
H:\Examples\coder-ex19875030\codegen\exe\myMatlabFunction>set "VSCMD_START_DIR=H:\Examples\coder-ex19875030\codegen\exe\myMatlabFunction"  
 
H:\Examples\coder-ex19875030\codegen\exe\myMatlabFunction>call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\\VC\Auxiliary\Build\vcvarsall.bat" amd64_x86  
********************************************************************** 
** Visual Studio 2017 Developer Command Prompt v15.0.26730.12 
** Copyright (c) 2017 Microsoft Corporation 
********************************************************************** 
[vcvarsall.bat] Environment initialized for: 'x64_x86' 
 
Microsoft (R) Program Maintenance Utility Version 14.11.25507.1 
Copyright (C) Microsoft Corporation.  All rights reserved. 
 
	cl  -c -nologo -GS -W4 -DWIN32 -D_MT -MTd -D_CRT_SECURE_NO_WARNINGS  /Od /Oy-  -DMODEL=myMatlabFunction -DHAVESTDIO -DUSE_RTMODEL @myMatlabFunction_rtw_comp.rsp -Fo"myMatlabFunction_initialize.obj" "H:\Examples\coder-ex19875030\codegen\exe\myMatlabFunction\myMatlabFunction_initialize.c" 
myMatlabFunction_initialize.c 
	cl  -c -nologo -GS -W4 -DWIN32 -D_MT -MTd -D_CRT_SECURE_NO_WARNINGS  /Od /Oy-  -DMODEL=myMatlabFunction -DHAVESTDIO -DUSE_RTMODEL @myMatlabFunction_rtw_comp.rsp -Fo"myMatlabFunction_terminate.obj" "H:\Examples\coder-ex19875030\codegen\exe\myMatlabFunction\myMatlabFunction_terminate.c" 
myMatlabFunction_terminate.c 
	cl  -c -nologo -GS -W4 -DWIN32 -D_MT -MTd -D_CRT_SECURE_NO_WARNINGS  /Od /Oy-  -DMODEL=myMatlabFunction -DHAVESTDIO -DUSE_RTMODEL @myMatlabFunction_rtw_comp.rsp -Fo"myMatlabFunction.obj" "H:\Examples\coder-ex19875030\codegen\exe\myMatlabFunction\myMatlabFunction.c" 
myMatlabFunction.c 
	cl  -c -nologo -GS -W4 -DWIN32 -D_MT -MTd -D_CRT_SECURE_NO_WARNINGS  /Od /Oy-  -DMODEL=myMatlabFunction -DHAVESTDIO -DUSE_RTMODEL @myMatlabFunction_rtw_comp.rsp -Fo"myMatlabFunction_main.obj" "H:\Examples\coder-ex19875030\myMatlabFunction_main.c" 
myMatlabFunction_main.c 
### Creating standalone executable "H:\Examples\coder-ex19875030\myMatlabFunction.exe" ... 
	link /MACHINE:X86 /DEBUG /DEBUGTYPE:cv  /INCREMENTAL:NO /NOLOGO kernel32.lib ws2_32.lib mswsock.lib advapi32.lib -out:H:\Examples\coder-ex19875030\myMatlabFunction.exe @myMatlabFunction_rtw.rsp   
### Created: H:\Examples\coder-ex19875030\myMatlabFunction.exe 
### Successfully generated all binary outputs. 
myMatlabFunction(3.1416) = 6.2832 

Дополнительный Шаг: не укажите набор инструментальных средств

Не указывать набор инструментальных средств, введите:

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

Похожие темы