Nano Hash - криптовалюты, майнинг, программирование

Создайте оболочку C++/CLI для собственного кода C++

В настоящее время мне нужно написать оболочку C++/CLI для собственной библиотеки C++ (TetGen) для последующего использования в проекте C#. Я прочитал довольно много статей о том, как это сделать, но не могу разобраться с ошибками компоновщика. Парень по имени «Сэм Агтен» тоже пытался добиться этого, как он пишет в своем блоге, который привел меня к серии по C++ Interop (Часть 1, Часть 2, Часть 3, Часть 4, Часть 5), где Часть 3 должна объяснять, как что делать Я выполняю.

Поскольку Сэм хотел интегрировать TetGen с Unity, ему в конце концов пришлось прибегнуть к C-Style-Wrappers. Теперь, если я не совсем ошибаюсь, я пытался использовать C-Style-Wrappers в предыдущем связанном проекте.

Поскольку мой обернутый TetGen должен работать на Windows Server (кажется, 2008), мой первый вопрос: Будет ли C++/CLI-Wrapper работать в серверной среде?

Я начал писать очень простую оболочку в соответствии с вышеупомянутой частью 3, которая с треском провалилась. Во всяком случае, я попытался создать простую библиотеку-оболочку в соответствии с направлением мысли, которым я хочу поделиться с вами. Я начал с создания C#-проекта, который в конечном итоге должен использовать мою обернутую библиотеку, и добавил сначала новый проект из «Win32»-подраздела C++-проектов «SimpleAdd».

//SimpleAdd.h
class _declspec(dllexport) SimpleAdd
{
public:
    SimpleAdd();
    ~SimpleAdd();

    int Add(int a,int b);
};

//SimpleAdd.cpp
#include "SimpleAdd.h"
int SimpleAdd::Add(int a, int b)
{
    return a+b;
}

В настройках проекта я убедился, что он скомпилирован в статическую библиотеку (*.lib) и без поддержки CLR. Из определения препроцессора я предполагаю, что библиотека предназначена для систем x86: «WIN32». Все осталось практически на стандартных значениях. Если я щелкну правой кнопкой мыши => build, он успешно создаст библиотеку с именем «SimpleAdd.lib».

В других сообщениях мне было указано на одну вещь: если я открываю библиотеку в DependencyWalker, я получаю сообщение об ошибке: «Не найдена подпись DOS или PE. Этот файл не является допустимым 32-разрядным или 64-разрядным модулем Windows», который как-то расстраивает. Что мне нужно сделать, чтобы DependencyWalker перестал показывать эту ошибку, так как я думаю, что эта проблема 32/64 может указывать на решение.

Во всяком случае, у меня есть моя библиотека, теперь я хочу ее завернуть. Поэтому я создал новый проект в своем решении под названием «AddWrapper», используя шаблон CLR-ClassLibrary ветки C++.

// AddWrapper.h
#pragma once
#include "..\SimpleAdd\SimpleAdd.h"
using namespace System;

namespace AddWrapper {
public ref class ManagedSimpleAdd
{
private:
    SimpleAdd *sa;
public:
    ManagedSimpleAdd();
    ~ManagedSimpleAdd();
    int Add(int a, int b);
};
}

//AddWrapper.cpp
#include "AddWrapper.h"
using namespace AddWrapper;

ManagedSimpleAdd::ManagedSimpleAdd() : sa(new SimpleAdd())
{
}

ManagedSimpleAdd::~ManagedSimpleAdd(){delete sa;}

int ManagedSimpleAdd::Add(int a, int b)
{
    return sa->Add(a,b);
}

Поскольку оба C++-проекта находятся в разных папках на одном иерархическом уровне, я указал относительный путь к заголовочному файлу. В настройках проекта теперь у меня стандартная конфигурация .dll и переключатель /clr. В моих папках VC++ я добавил путь к каталогу отладки всей моей души, потому что именно здесь компилируется указанная библиотека. В моих настройках компоновщика в разделе «Дополнительные зависимости» я добавил имя: «SimpleAdd.lib».

Однако, когда я хочу собрать свою оболочку, возникает проблема, а точнее 5 из них:

Ошибка Fehler 3 LNK2028: Nicht aufgel÷stes Token (0A00000B) ""public: __thiscall SimpleAdd::SimpleAdd(void)" (??0SimpleAdd@@$$FQAE@XZ)", auf das in Funktion ""public: __clrcall AddWrapper ::ManagedSimpleAdd::ManagedSimpleAdd(void)" (??0ManagedSimpleAdd@AddWrapper@@$$FQ$AAM@XZ)" verwiesen wird. %path%\AddWrapper\AddWrapper.obj AddWrapper Fehler 4 error LNK2028: Nicht aufgel÷stes Token (0A00000C) ""public: __thiscall SimpleAdd::~SimpleAdd(void)" (??1SimpleAdd@@$$FQAE@XZ)" , auf das in Funktion ""public: void * __thiscall SimpleAdd::scalar deleting destructor'(unsigned int)" (??_GSimpleAdd@@$$FQAEPAXI@Z)" verwiesen wird. %path%\AddWrapper\AddWrapper.obj AddWrapper Fehler 5 error LNK2019: Verweis auf nicht aufgel÷stes externes Symbol ""public: __thiscall SimpleAdd::SimpleAdd(void)" (??0SimpleAdd@@$$FQAE@XZ)" in Funktion ""public: __clrcall AddWrapper::ManagedSimpleAdd::ManagedSimpleAdd(void)" (??0ManagedSimpleAdd@AddWrapper@@$$FQ$AAM@XZ)". %path%\AddWrapper\AddWrapper.obj AddWrapper Fehler 6 error LNK2019: Verweis auf nicht aufgel÷stes externes Symbol ""public: __thiscall SimpleAdd::~SimpleAdd(void)" (??1SimpleAdd@@$$FQAE@XZ)" in Funktion ""public: void * __thiscall SimpleAdd::scalar, удаляющий деструктор'(unsigned int)" (??_GSimpleAdd@@$$FQAEPAXI@Z)". %path%\AddWrapper\AddWrapper.obj AddWrapper Fehler 7 error LNK1120: 4 nicht aufgel÷ste Externe %path%\Debug\AddWrapper.dll 1 1 AddWrapper

Теперь, что может быть причиной этих ошибок? Является ли это ошибкой библиотеки? Я пропустил, чтобы указать что-то еще?


Ответы:


1

Что мне нужно сделать, чтобы DependencyWalker перестал показывать эту ошибку

Не компилируйте в файл lib! Это не исполняемый файл и не библиотека с динамической компоновкой, поэтому у нее нет подписи PE. Вы можете создать статическую библиотеку и скомпоновать ее внутри вашей сборки C++/CLI (если хотите), или вы можете просто поместить весь этот код в свою сборку C++/CLI. Вам решать.

в чем может быть причина этих ошибок?

Вы напрямую включили заголовочный файл, позвольте мне выделить ваш код:

class _declspec(dllexport) SimpleAdd

Как вы можете видеть, вы на самом деле компилируете с помощью _declspec(dllexport), вы не говорите компилятору импортировать такой класс из библиотеки, а экспортируете его (и компоновщик будет жаловаться, потому что вы объявили этот класс, но нет никакой реализации) . Когда вы включаете класс, он должен быть объявлен с помощью _declspec(dllimport).

class _declspec(dllimport) SimpleAdd

Обычно этот трюк реализуется с помощью макросов препроцессора. Позвольте мне сделать упрощенный пример. В вашем файле SimpleAdd.h вы можете объявить:

#if defined(SIMPLEADD_LIB)
#define SIMPLEADD_EXPORTED _declspec(dllexport)
#else
#define SIMPLEADD_EXPORTED _declspec(dllimport)
#endif

Затем измените свой код на

class SIMPLEADD_EXPORTED SimpleAdd

В вашем проекте SimpleAdd вы определяете макрос (из настроек проекта) с именем SIMPLEADD_LIB. Это приведет к тому, что ваша библиотека будет собрана с dllexport (потому что из библиотеки вы экспортируете этот класс), но в вашей оболочке C++/CLI будет объявлена ​​как dllimport (правильно, потому что SIMPLEADD_LIB не объявлено, и вы импортируете этот класс).

29.04.2014
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..