Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Как упаковать код на разных языках программирования в один exe или dll файл  (Прочитано 37489 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« : 27-04-2013 23:08 » 

Очевидный способ собрать решение, написанное на нескольких языках программирования .NET - это код на каждом языке оформить отдельной сборкой (assembly) в виде dll, а затем подключить их к исполняемому exe файлу основной программы. Этот способ предлагается Visual Studio - к другим она не приспособлена. Не всегда удобно создавать решение из множества файлов, и средства самого .NET позволяют справиться с этой задачей. Главная сложность состоит в том, чтобы и сохранить удобную среду разработки Visual Studio, и получить желаемое решение.

Инфраструктура


Для начала создадим инфраструктуру.

1) Создаём пустой solution: в системном меню выбираем File/New Project. В открывшем диалоге выбираем Other Project Types/Visual Studio Solutions\Blank Solution. Задаём имя, допустим, mulilang. Создаём solution.

2) Добавляем в solution пустой проект C#: правой кнопкой мыши кликаем на Solution и в контекстном меню выбираем Add/New Project. В открывшемся диалоге выбираем Visual C#/Windows/Empty Project. Задаём имя, допустим, csl. Создаём проект.

3) Изменяем тип проекта csl на нестандартный. Для этого:

3.1) Правой кнопкой мыши кликаем на проект csl и в контекстном меню выбираем Unload Project. Затем опять правкой кнопкой мыши кликаем на проект csl и в контекстном меню выбираем Edit.

3.2) В открывшемся XML-файле проекта находим элемент Project/PropertyGroup/OutputType. Стандартным редактором свойств туда можно установить только три значения: "Exe" (Console Application), генерирующий файл типа exe, запускающийся в чёрном окне консоли, "Winexe" (Windows Application), генерирующий файл типа exe, запускающийся без окна консоли, и "Library" (Class Library), генерирующий файл типа dll, пригодный к подключению к другим проектам типа exe и dll.

Есть недокументированное значение: "Module", генерирующее файл типа netmodule. Этот файл подобен библиотеке dll и может подключаться к другим exe и dll. Разница заключается в том, что любой exe и dll представляет собой законченную сборку (assembly), а netmodule - только составную часть какой-то сборки. Т.е. при помощи модулей в .NET можно создавать многофайловые сборки. Например, такие, части которых написаны на разных языках программирования.

И вот нам нужно в XML-узле Project/PropertyGroup/OutputType записать значение Module, заставящее комплиятор C# сгенерировать файл модуля.

3.3) Поменяв значение, сохраняем файл проекта. Обязательно закрываем окно редактора. Правой кнопкой мыши кликаем на проект csl и в контекстном меню выбираем Reload Project.

Теперь, если открыть свойства проекта, мы увидим там на вкладке Application в выпадающем списке Output Type какое-то одно из стандартных значений, что неправильно, но на самом деле, если не трогать этот выпадающий список, там сохранится значение Module. Остальные свойства проекта можно менять свободно и даже конвертировать solution в новые версии Visual Studio - значение не испортится.

4) Наполним проект содержанием. Правой кнопкой мыши кликаем на проект csl и выбираем в контекстном меню пункт Add/New Item. В открывшемся диалоге выбираем Class. Зададим имя, допустим, CSL. Добавляем класс в проект. Оформим его как точку входа в приложение: добавим метод Main и какой-нибудь вывод на экран.

Код: (C#)
using System;

namespace csl
{
    class CSL
    {
        static void Main(string[] argc)
        {
            Console.WriteLine("Hello world.");
            Console.ReadKey();
        }
    }
}

5) Делам Build для solution и убеждаемся, что всё нормально. Ищем на диске наш solution, открываем папку multilang/csl/bin/<Имя конфигурации> (Debug или Release) и смотрим, что там появился файл csl.netmodule. Этот файл не является исполняемым.

6) Чтобы наша программа заработала, нужно полученный модуль подключить к какому-нибудь exe. При использовании редактора связей .NET al (который вызывают компиляторы C#, VB и других языков .NET) можно построить только такие exe и dll, у которых модули остаются внешними. Т.е. для запуска программы рядом с exe-файлом должны находится файлы netmodule. Это нам не интересно. А вот редактор связей C++ link умеет собирать такие exe, внутрь которых встраиваются netmodule. Этим мы и воспользуемся.

7) Добавим в solution пустой проект C++: правой кнопкой мыши кликаем на multilang и в контекстном меню выбираем Add/New Project. В открывшемся диалоге выбираем Visual C++/General/Empty Project. Задаём имя, допустим, app. Создаём проект.

7.1) Этот проект будет у нас главным для запуска, поэтому правой кнопкой мыши кликаем на app и в контекстном меню выбираем Set as StartUp Project.

8 ) Поскольку нас интересует только редактор связей, никакого полезного содержания в проекте app у нас не будет. Но чтобы процесс сборки вообще запускался, мы добавим один пустой файл C++. Кликаем правой кнопкой мыши на проект app, в контекстном меню выбираем пункт Add/New Item. В открывшемся диалоге выбираем C++ File. Зададим имя, допустим, stub. Добавляем файл в проект.

9) Сборка проектов C++ отличается от сборок проектов других языков местом расположения файлов результата. Они будут попадать в папку multilang/<Имя конфигурации> - т.е. находятся на уровне solution, а не отдельного проекта.

Чтобы наш модуль попадал именно туда, нужно изменить свойства проекта csl. Кликаем правой кнопкой мыши на проект csl и выбираем в контекстном меню пункт Properties. Находим на вкладке Build элемент Output path. Если текущая конфигурация Debug, там написано "bin\Debug\". Меняем на "..\Debug\". Сверху в выпадающем списке Configuration выбираем следующую конфигурацию Release и в ней тоже меняем значение на "..\Release\". Возвращаем исходную конфигурацию, сохраняем и закрываем окно свойств проекта csl.

10) Связываем проекты зависимостью: кликаем правой кнопкой мыши на проекте app и в контекстном меню выбираем Project Dependencies. В открывшемся диалоге ставим галочку на проекте csl и закрываем окно.

11) Настраиваем редактор связей: кликаем правой кнопкой мыши на проекте app и в котекстном меню выбираем Properties. В открывшемся окне сверху в выпадающем списке Configuration выбираем All configurations.

11.1) В дереве выбираем элемент Configuration Properties/Linker/Input. В поле Additional Dependencies записываем значение (с кавычками) "$(OutDir)\csl.netmodule".

11.2) В дереве выбираем элемент Configuration Properties/Linker/System. В поле SubSystem выбираем значение Console. (Это для нашего случая, но в остальных случаях какое-то конкретное значение этой настройки нужно указывать обязательно.)

11.3) В дереве выбираем элемент Configuration Properties/Linker/Advanced. В поле Entry Point записываем значение "csl.CSL.Main" - полное имя метода Main точки входа в программу (см. код выше).

Закрываем окно свойств.

12) Надо проверить результат. Нажимаем зелёную стрелку запуска или кнопку F5. Всё должно собраться, программа должна запуститься, и в окне консоли появится надпись "Hello world.". Нажатием любой клавиши можем завершить работу нашей программы. При желании можно скопировать файл multilang/<Имя конфигурации>/app.exe в другое место, где нет файлов netmodule, и убедиться, что и там наша программа успешно запускается.

Взаимодействие модулей


Итак, мы получили инфраструктуру для многоязыковых сборок. Основная её идея заключается в том, что отдельные блоки кода оформляются не в виде Class library, а в виде Module при помощи описанной выше подмены свойств проектов.

Полученные файлы netmodule с их полными путями необходимо добавить в Linker/Input/Additional Dependencies через пробел.

Другой вопрос, как организовать сборку модулей, ссылающихся друг на друга, поскольку воспользоваться стандартным механизмом ссылок (References) в свойствах проекта мы не можем - для ссылок нужны законченные сборки (dll, exe), а не модули.

К примеру, создадим модуль на языке VB.NET, который мы хотим вызывать из нашей программы на C#.

1) Добавим в solution пустой проект VB.NET и меняем его тип, как это описано выше в пунктах 2-3 предыдущего раздела. Назовём проект, допустим, vbl.

2) Отредактируем пути выходных файлов проекта vbl и привяжем его к проекту app, как это описано в пунктах 9-10 предыдущего раздела (с той лишь разницей, что вкладке Build в свойствах проекта C# соответствует вкладка Compile в свойствах проекта VB.NET). Также укажем файл "$(OutDir)\vbl.netmodule" в качестве входного для редактора связей проекта app (см. пункт 11.1 предыдущего раздела). Не следует забывать делать изменения свойств для All configurations, иначе возникнет разница между Debug и Release сборками.

3) Добавим класс Hello в проект vbl (аналогично пункту 4 предыдущего раздела) и в нём статический метод Hello для вывода какой-нибудь надписи на экран:
Код: (vb.net)
Public Class Hello

    Public Shared Sub Hello()
        Console.WriteLine("Hello VB.NET")
    End Sub

End Class

4) Соберём solution и убедимся, что всё хорошо собирается.

5) Теперь перед нами стоит задача вызвать vbl.Hello.Hello из метода csl.Program.Main. Для этого нужно связать проекты модулей, и это придётся сделать вручную.

5.1) Выгружаем проект csl и открываем его XML-файл редактором (см. пункт 3.1 предыдущего раздела). Находим в XML-файле секции Project/ItemGroup. Добавляем собственную секцию в элемент Project:
Код: (XML)
<ItemGroup>
        <AddModules Include="$(OutDir)\vbl.netmodule" />
</ItemGroup>
Редактор может показывать, что такой элемент некорректен для текущей схемы XML - не обращаем на это внимание. Сохраняем изменения и загружаем проект csl обратно (см. пункт 3.3 предыдущего раздела). Если модуль vbl.netmodule был успешно собран и находится в папке с прочими выходными файлами, он будет показан в дереве проекта csl пустой иконкой. Если файла модуля нет, то иконка будет преупреждающей жёлтой с вопросительным знаком.

5.2) Для предотвращения ошибок нужно задать правильный порядок сборки проектов в solution. Он устанавливается автоматически по зависимостям между проектами. Но поскольку в нашем случае зависимость нестандартная, Visual Studio не сможет определить порядок, и его следует указать вручную. Кликаем правой кнопкой мыши на multilang и выбираем в контекстном меню Project Build Order. В открывшемся окне на вкладке Dependencies выбираем проект csl в выпадающем списке Projects и в перечне ставим галочку на проекте vbl, тем самым вручную устанавливая зависимость.

5.3) Добавляем взаимодействие модулей. В проекте csl вставляем в нашу программу вызов нового модуля:
Код: (C#)
        static void Main(string[] argc)
        {
            vbl.Hello.Hello();
            Console.WriteLine("Hello C#.NET");
            Console.ReadKey();
        }
Редактор покажет, что пространство имён vbl и класс Hello ему неизвестны, не распознает всю строчку и не будет показывать подсказки при наборе кода. Тем не менее код правильный. Такова цена за использование недокументированных возможностей.

6) Собираем solution и запускаем программу - убеждаемся, что всё работает.
Hello VB.NET
Hello C#.NET


P.S. С самым интересным - добавлением C++ - всё не так гладко, об этом позже.
« Последнее редактирование: 27-04-2013 23:11 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 28-04-2013 15:24 » 

Особенности C++


C++.NET - особенный язык. На на нём возможно создавать модули и сборки, содержащие смешанный код: native (т.е. в машинном коде целевой платформы) и CLR (т.е. в байт-коде .NET). Процесс сборки кода C++ также отличается. В других языках компилятор сразу создаёт выходной файл нужного типа. В C++ в начале компилятор формирует объектные файлы (obj), и потом редактор связей их собирается в выходной файл нужного типа.

Для вызова из других языков код C++.NET может быть оформлен как модуль netmodule. Однако при этом на такой модуль накладывается существенное ограничение: он должен содержать только безопасный (safe) CLR-код. Соответственно любой native-код при этом становится недоступным, что нам неинтересно.

Но в качестве модулей компиляторы других языков и самого C++ охотно принимают объектные (obj) файлы CLR-кода. Такие файлы могут содержать символы из других obj-файлов, и в них может присутствовать как native, так и CLR-код. Однако в качестве модулей компиляторы не воспринимают статические библиотеки (lib-файлы). Это накладывает некоторые ограничения:  lib и netmodule содержат архив разных скомпилированных файлов, что удобно для экспорта всей их совокупности. Поскольку мы это удобство не можем использовать, то либо все экспортируемые для других модулей классы и функции нам нужно собрать в один obj-файл (через директиву #include в cpp-файле), либо придётся подключать всё множество obj-файлов - каждый obj-файл как отдельный модуль.

Поместить код C++ в имеющийся у нас проект app мы не можем, поскольку тогда нарушится порядок сборки модулей: сначала нужно собрать app, чтобы получить экспортируемые obj-файлы, затем собрать другие модули, затем собрать app в виде exe, подключив все собранные модули. По этой причине код C++ мы должны вынести в отдельный проект - наравне с проектами других языков, - чтобы он собиралась раньше зависящих от него других модулей.

1) Добавим в solution пустой проект типа Visual C++/CLR/CLR C++ Empty Project (см. пункт 7 первого раздела). Назовём проект, допустим, cppl.

2) Кликаем правой кнопкой мыши на проект cppl и в контекстном меню выбираем пункт Properties. В выпадающем списке Configuration выбираем All configurations. Идём на вкладку Configuration Properties/General, где в поле Configuration Type выбираем значение Static Library. Этим мы определяем выходной файл сборки проекта как библиотеку cppl.lib, помещаемую в папку выходных файлов solution. С её помощью редактор связей включит в exe-файл всё содержимое этого проекта. Закрываем окно свойств.

3) Напишем код. Кликаем правой кнопкой мыши на проекте cppl и в контекстном меню выбираем пункт Add/New Item. В открывшемся диалоге выбираем тип файла C++ File. Назовём его, допустим, cppl.cpp.
Код: (C++)
namespace cppl
{
        using namespace System;

        ref class Cppl
        {
        public:
                static void Hello()
                {
                        Console::WriteLine(L"Hello C++.NET");
                }
        };
}

4) Поскольку результат компиляции этого файла нам понадобится как модуль для других модулей, для единообразия размещения файлов модулей скопируем получающийся obj-файл из папки результатов сборки проекта в папку результатов нашего solution.

Для этого правой кнопкой мыши кликаем на проекте cppl, в контекстном меню выбираем пункт Properties. В выпадающем списке Configuration выбираем пункт All configurations. Открываем вкладку Configuration Properties/Build Events/Post-Build Event. В поле Command Line пишем команду
Код:
copy /Y "$(ProjectDir)\$(ConfigurationName)\cppl.obj" "$(OutDir)"
Закрываем окно свойств проекта.

5) Несмотря на то, что файл cppl.obj и так автоматически включён cppl.lib и поэтому попадёт в exe-файл, редактор связей в проекте app будет требовать этот файл в списке модулей наравне с прочими модулями именно потому, что другие модули на него ссылаются.

Кликаем на проекте app правой кнопкой мыши и в контекстном меню выбираем пункт Properties. В открывшемся окне сверху в выпадающем списке Configuration выбираем All configurations. В дереве выбираем элемент Configuration Properties/Linker/Input. В поле Additional Dependencies через пробел после уже имеющихся там модулей записываем значение (с кавычками) "$(OutDir)\cppl.obj".

6) Подключим решение на C++ к какому-нибудь из других модулей. Для разнообразия - к проекту vbl. Делается это так же, как описано в пункте 5.1 предыдущего раздела, только нужно указать значение "$(OutDir)/cppl.obj". Также укажем, что проект vbl зависит от проекта cppl (аналогично пункту 5.2 предыдущего раздела). Ну и добавим вызов в код VB:
Код: (vb.net)
Public Class Hello
    Public Shared Sub Hello()
        cppl.Cppl.Hello()
        Console.WriteLine("Hello VB.NET")
    End Sub
End Class

7) Собираем и запускаем приложение, проверяем, что всё нормально работает:
Hello C++.NET
Hello VB.NET
Hello C#.NET


Теперь подключим native-код. Вызываться он может из CLR-кода C++, а для других языков простых способов нет. Теоретически возможно использование атрибута DllImport. Учитывая, что процесс не будет сам себя загружать ещё раз в верхние адреса своего адресного пространства, для такого способа придётся поколдовать с адресами смещения импортируемых функций и с редактором связей. Этим мы заниматься не станем - проще использовать обёртку (wrapper) из CLR-кода C++.

1) Добавим в solution пустой проект C++ (см. пункт 2 первого раздела). Назовём проект cppn.

2) Изменим тип проекта на Static Library (см. пункт 2 предыдущего перечня). Установим зависимость проекта app от cppn (см. пункт 10 первого раздела). Теперь библиотека cppn.lib будет включена в наш exe-файл.

3) Добавим в проект cppn файл кода native.cpp (см. пункт 3 предыдущего перечня) и заголовочный файл native.h (аналогично, только тип файла Header File).

Заголовочный файл предназначен для декларации native-функции для их вызывающего CLR-кода. По этой причине к оформлению заголовочного файла подходим внимательно и следим, чтобы компилятор правильно разграничивал CLR- и native-код.
Код: (C++)
#pragma once
#pragma managed(push)
#pragma unmanaged

void native();

#pragma managed(pop)
Такое решение обработает заголовок как native-код вне зависимости от текущего режима компиляции.

Файл кода собирается в проекте без поддержки CLR, поэтому в нём дополнительные директивы не нужны
Код: (C++)
#include <iostream>
#include "native.h"

using namespace std;

void native()
{
        wcout << L"Hello Native C++" << endl;
}

4) Подключим созданный native-код к CLR-коду. Сначала установим зависимость проекта cppl от проекта cppn (аналогично пункту 10 первого раздела). Затем в проекте cppl вносим изменения в код:
Код: (C++)
#include "../cppn/native.h"

namespace cppl
{
        using namespace System;

        ref class Cppl
        {
        public:
                static void Hello()
                {
                        native();
                        Console::WriteLine(L"Hello C++.NET");
                }
        };
}

5) Можно собирать и запускать программу:
Hello Native C++
Hello C++.NET
Hello VB.NET
Hello C#.NET


P.S. Вроде как тема раскрыта...
« Последнее редактирование: 28-04-2013 15:26 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 28-04-2013 15:28 » 

Цитата
В других языках компилятор сразу создаёт выходной файл нужного типа.
Ой....
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 28-04-2013 17:16 » 

Sla, чего? ты видел obj-файлы компилятора C# или VB?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 28-04-2013 17:21 » 

Я и ни C#, ни VB (а это компилятор?) не видел.

Но видел obj от другого языка
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
zubr
Гость
« Ответ #5 : 28-04-2013 17:31 » 

Delphi-компилятор умеет создавать obj-файлы.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 29-04-2013 11:56 » 

Есть проблема со сборкой solution. Build делает хорошо. Даже если сделать Clean и собирать весь solution с начала, всё равно делает Build хорошо - последовательно. А вот Rebuild пытается делать параллельно, причём полагает, что VB и C# проекты параллельно собирать можно, и вот тут происходит ошибка: netmodule не успевают создаваться, как уже стартует сборка проектов, где они нужны.

Поищу, как бы это победить.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 29-04-2013 12:06 » 

Уточнение: rebuild не работает, только если до этого выполнялся build или rebuild. Если предыдущим шагом было clean, то rebuild также работает.

А как бы их объединить: чтобы при rebuild в начале всегда автоматически делался clean?
« Последнее редактирование: 29-04-2013 12:15 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dmitry
Помогающий

ru
Offline Offline

« Ответ #8 : 29-04-2013 12:52 » 

Может, параллельную сборку отключить?
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 29-04-2013 15:20 » 

Dmitry, совет хороший, осталось понять, как. Речь, кстати, тут идёт о разных VS - вышеописанное работает начиная с 2005. Мне надо для 2008. MSBuild вместо студии не предлагать.

Если не делать clean, происходит фактическая ошибка: сборщик видит, что файлы проекта Y, от которых зависит сборка проекта X, имеются, и с чистой совестью стартует сборку, но при этом запущена сборка того самого проекта Y, и к моменту когда X хочет прочитать эти файлы, Y их уже удалил и готовит новые - коллизия. Если делать clean, файлов нет, сборка запускается последовательно - по мере появления файлов.
« Последнее редактирование: 29-04-2013 15:23 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dmitry
Помогающий

ru
Offline Offline

« Ответ #10 : 29-04-2013 15:42 » 

Dimka,VS 2012, Options->Projects and Solutions->Build and Run. Там можно задать максимальное количество параллельных билдов. Это оно?
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 29-04-2013 16:03 » 

Dmitry, такое есть в 2008-й, но не помогает. Значит моё предположение о причине неверное.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 02-05-2013 22:13 » 

Замечания:


1) В общем-то можно промежуточный CLR C++ проект не создавать, а в native C++ static library проекте создать отдельный файл, в свойствах которого:

Во всех конфигурациях:

а) Включить сборку CLR (Configuration Properties/General/Compile With Common Language Runtime).

б) Изменить место нахождения файла результата (Configuration Properties/Output Files/Object File Name) - указать "$(OutDir)\$(ProjectName).obj".

В Debug конфигурации:

а) Поменять формат отладочной информации (Configuration Properties/General/Debug Information Format) - вариант /ZI несовместим с /clr, поэтому выбрать /Zi (Program Database).

б) Поменять порядок обработки исключений (Configuration Properties/Code Generation/Enable C++ Exceptions) - /EHsc (Yes) несовместим с /clr, поэтому выбрать либо /EHa (Yes with SEH Exceptions) или No

в) Поменять порядок обработки Debug-проверок (Configuration Properties/Code Generation/Basic Runtime Checks) - выбрать Default.

Но всё это годится при условии, что в этом файле с CLR интерфейсом нет никакого кода из Framework, поскольку никакие Reference к такому проекту не подключены и версия .NET не выбрана. Если это нужно, то либо через директиву #using подключать references прямо в коде, либо делать промежуточный CLR C++ Static Library проект.


2) Шаблоны C++ (templates) даже в CLR-классах обрабатываются как шаблоны C++, а не как Generic-типы .NET. По этой причине они не попадают в obj-файл и недоступны для модулей на других языках.

Вместо
Код: (C++)
template<class T> class X { /* ... */ };

нужно писать
Код: (C++)
generic<class T> class X { /* ... */ };

тогда будет как надо.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #13 : 16-06-2013 11:56 » 

Также полезно обратить внимание на этот феномен:
https://forum.shelek.ru/index.php/topic,29455.0.html
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #14 : 02-10-2013 18:45 » 

Ещё одна заметка. Не C++ проекты (C#, VB) для правильной линковки должны собираться под AnyCPU. Попытка указать платформу явным образом x86 или x64 вызывает ошибку линкера: он требует безопасной сборки, не считая таковой сборку под конкретную платформу.

Тут стоит обратить внимание, что для вызовов внешних dll и импорта их функций в обычных проектах как раз таки требуется явное указание платформы, иначе попытка загрузки dll приведёт к исключительной ситуации BadImageFormat. Однако с учётом того, что хостовый процесс для модуля собирается линкером C++ с явным указанием платформы, может быть в случае netmodule такой ошибки не будет. Я ещё не проверил - пока не было надобности.


Ну и ещё ремарка: netmodule не может включать в себя ресурсы - также, как obj и lib-файлы в C++.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
nik
Новенький

ru
Offline Offline

« Ответ #15 : 18-05-2015 06:00 » 

есть у меня готовый проект написанный на с# exe

Добавлено через 5 минут и 43 секунды:
есть у меня готовый проект написанный на с# exe оконое приложение под виндовс (Server.exe). хотел к нему добавить как тут написанно нативный код на с++.
Создал для линковки проект app. и в качестве выходного файла указал Server.exe. Из C# приложения сдела сборку netmodule. Всё слинковалось хорошо. но вот при работе приложения оно падет не может выполнить вот этот код assembly.GetManifestResourceStream(resourcePath) где assemnly это Server.exe. можно это как нибуть побороть ?
« Последнее редактирование: 18-05-2015 06:06 от nik » Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines