Сначала DllNotFoundException, затем EntryPointNotFoundException при вызове чистой функции C из C # - PullRequest
3 голосов
/ 03 апреля 2012

Я пытаюсь использовать код на 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 для " Компилятор для C / C ++ / Objective-C " с Apple LLVM3.0 до LLVM GCC 4.2 , но я все еще получаю то же исключение.
  2. Я также видел эту моно документацию , в которой говорится, что mono использует GLib для загрузки библиотек, а в Glib есть ошибка в Mac OS X, которая заключается в том, чтораспознавать библиотеки .dylib.Я удалил библиотеки .dylib и попробовал еще раз, но получал то же исключение.
  3. Также В документации Apple говорится, что каждый загружаемый пакет должен иметь основной класс,и если пользователь не указывает, какой класс является основным, NSBundle будет использовать первый класс, показанный в проекте Xcode, в качестве основного класса.Ну, я предполагаю, что созданный мной пакет является загружаемым, но поскольку он представляет собой просто статическую библиотеку, созданную из C, он буквально не имеет никакого класса.Когда я посмотрел на info.plist моего проекта , запись Principal Class просто пуста.Может ли это быть проблемой?Если да, то как мне это решить?
  4. Также в документации Apple я увидел кое-что, чего я не совсем понимаю:

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

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

1 Ответ

2 голосов
/ 29 апреля 2012

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

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

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

В моем случае функция, которая выбрасывает исключение 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

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

...