Сначала DllNotFoundException, затем EntryPointNotFoundException при вызове чистой функции C из C#

Я пытаюсь использовать код на C в Unity3D pro.

Мой основной подход заключается в том, чтобы (1) встроить исходный код C в статическую библиотеку (2) создать пустой пакет и связать его с библиотекой (3) импортировать пакет в Unity 3D pro (в качестве плагина).

Я в основном следовал этому уроку.

Это работало для меня некоторое время до недавнего времени, когда я обновлял свой код C и перекомпилировал и перестраивал библиотеку и пакет, все идет не так, как надо...

Когда я впервые импортировал пакет, я получил исключение DllNotFoundException.

На этом этапе мой пакетный проект представлял собой просто кучу библиотек - библиотека, построенная из моего исходного кода (который представляет собой файл.a) и несколько других библиотек, от которых, как мне кажется, зависит библиотека.a (другие библиотеки имеют расширение.dylib).).

Я добавил один файл test.c в комплект. Тестовый файл.c содержит только две строки:

#include <stdio.h>
#include "ccn.h"

char* say()
{
    return "hi";
}

в котором ccn.h является заголовочным файлом из моего исходного кода на языке C.

После того, как я перестроил пакет, DllNotFoundExeption исчез, но я получил EntryPointNotFoundException.

Вот что я думаю:

  1. Поскольку Xcode настолько интеллектуален, я предполагаю, что, добавляя простой файл test.c, Xcode изменил некоторые настройки моего пакета для меня. И я полагаю, что это причина, почему DllNotFoundException ушла в первую очередь. Я правильно думаю?
  2. Я думаю, что для решения проблемы EntryPointNotFound мне также придется изменить некоторые настройки проекта пакета - но я не знаю, как... Пожалуйста, помогите мне...

Большое и большое спасибо!

редактировать

  1. Я видел этот поток, предлагающий, что, поскольку XCode использует g++ для компиляции, мне понадобится extern "C", даже если мой неуправляемый код находится на чистом C. Я изменил настройку цели в XCode4 для " Compiler for C / C++ / Objective-C " от Apple LLVM 3.0 до LLVM GCC 4.2, но я все еще получаю то же исключение.
  2. Я также видел эту моно документацию, в которой говорится, что mono использует GLib для загрузки библиотек, и у Glib есть ошибка в Mac OS X, которая заключается в том, что он не распознает библиотеки.dylib. Я удалил библиотеки.dylib и попробовал еще раз, но получал то же исключение.
  3. Также в документации Apple говорится, что каждый загружаемый пакет должен иметь основной класс, и если пользователь не указывает, какой класс является основным, NSBundle будет использовать первый класс, показанный в проекте XCode, в качестве основного класса. Ну, я предполагаю, что созданный мной пакет является загружаемым пакетом, но поскольку он представляет собой просто статическую библиотеку, созданную из C, он буквально не имеет никакого класса. Когда я посмотрел на info.plist моего проекта, запись основного класса просто пуста. Может ли это быть проблемой? Если да, то как мне это решить?
  4. Также в документации Apple я увидел кое-что, чего я не совсем понял:

    Если загружаемый пакет представляет собой плагин, разработчик хост-приложения обычно предоставляет интерфейс для архитектуры плагина в платформе. Эта структура обычно содержит класс, от которого наследуются все основные классы подключаемого модуля, или протокол (формальный или неформальный) для принятия основным классом подключаемого модуля.

    Я уверен, что загружаемый пакет, который я создаю, является плагином. Я импортирую пакет в Unity3D. Означает ли это, что я должен определить основной класс из Unity? Как?

1 ответ

Решение

Проблема имеет простое решение:

сначала попробуйте любую функцию, которая дает вам исключение EntryPointNotFoundException в файле test.c.

Под "попыткой" я подразумеваю, чтобы функция вызывалась в вашем main() и сначала проверялась в C.

В моем случае функция, которая выбрасывает исключение EntryPointNotFoundException, называется ccn_run(). Итак, я сделал следующие вещи:

  1. добавить функцию main() в test.c
  2. введите ccn_run () в функцию main()
  3. добавить цель командной строки в проект Xcode и протестировать ее

Я попробовал это, и функция работает нормально в C, теперь волшебная вещь состоит в том, что когда я перестраиваю пакет (без удаления функции main() и вызова ccn_run () внутри него), Unity может вызвать функцию ccn_run () без проблем!

Я не мог объяснить, почему это решает мою проблему, но это работает для меня уже почти месяц. Недавно Xcode обновился до 4.3.2, и я попробовал тот же подход снова, все еще работает. Я думаю, возможно, добавление функции main() помогает определить точку входа?

Наконец, я задокументировал весь процесс импорта кода C в Unity, и я рад поделиться с ним здесь: https://docs.google.com/document/d/1vAeupNQlBTY3y3Bma5Jo_Hs4JRYm6FoEc4vQN0WBGNg/edit

Мой пример кода:

  1. Проект Xcode: https://github.com/CherryQu921/CCNxPlugin
  2. Проект Unity: https://github.com/CherryQu921/cqs

Надеюсь, что этот ответ особенно помогает мой урок!

Другие вопросы по тегам