Указатель NULL
- это тот, который указывает на никуда. Когда вы разыскиваете указатель p
, вы говорите «дайте мне данные в месте, хранящемся в« p ». Когда p
является нулевым указателем, местоположение, хранящееся в p
, является nowhere
, вы говорите «Дайте мне данные в месте« нигде ». Очевидно, он не может этого сделать, поэтому он выбрасывает NULL pointer exception
.
В общем, это потому, что что-то не было правильно инициализировано.
Если Вы не должны использовать классы от обеих платформ одновременно, и Вы нацелены на платформы, которые поддерживают NSBundle разгрузка (OS X 10.4 или позже, никакая поддержка GNUStep), и производительность действительно не является проблемой для Вас, я полагаю, что Вы могли загрузить одну платформу каждый раз, когда необходимо использовать класс от него, и затем разгрузить его и загрузить другой, когда необходимо использовать другую платформу.
Моя начальная идея состояла в том, чтобы использовать NSBundle для загрузки одной из платформ, затем скопировать или переименовать классы в той платформе, и затем загрузить другую платформу. Существует две проблемы с этим. Во-первых, я не мог найти, что функция скопировала данные, на которые указывают, чтобы переименовать или скопировать класс, и любые другие классы в той первой платформе, которые ссылаются на переименованный класс, теперь сослались бы на класс от другой платформы.
Вы не должны были бы скопировать или переименовать класс, если бы был способ скопировать данные, на которые указывает IMP. Вы могли создать новый класс и затем скопировать по ivars, методам, свойствам и категориям. Намного больше работы, но это возможно. Однако у Вас все еще была бы проблема с другими классами в платформе, ссылающейся на неправильный класс.
РЕДАКТИРОВАНИЕ: принципиальное различие между C и временем выполнения Objective C, насколько я понимаю, когда библиотеки загружаются, функции в тех библиотеках содержат указатели на любые символы, на которые они ссылаются, тогда как в Objective C, они содержат строковые представления названий thsoe символов. Таким образом, в Вашем примере, можно использовать dlsym, чтобы получить адрес символа в памяти и присоединить его к другому символу. Другой код в библиотеке все еще работает, потому что Вы не изменяете адрес исходного символа. Objective C использует таблицу поиска для имен класса сопоставления к адресам, и это - отображение 1-1, таким образом, у Вас не может быть двух классов с тем же именем. Таким образом, для загрузки обоих классов одному из них нужно было изменить их имя. Однако, когда другие классы должны получить доступ к одному из классов с тем именем, они попросят у таблицы поиска ее адреса, и таблица поиска никогда не будет возвращать адрес переименованного класса, учитывая имя исходного класса.
Добавление префикса файлов является простым решением, о котором я знаю. У Cocoadev есть страница пространства имен, которая является усилием сообщества избежать конфликтов пространства имен. Не стесняйтесь добавлять свое собственное к этому списку, я верю тому, для именно это это.
Если бы у Вас есть коллизия, я предложил бы, чтобы Вы думали трудно о том, как Вы могли бы осуществить рефакторинг одну из платформ из Вашего приложения. Наличие коллизии предполагает, что эти два делают подобные вещи, как это, и Вы, вероятно, могли обойти использование дополнительной платформы просто путем рефакторинга приложения. Мало того, что это решило бы Вашу проблему пространства имен, но и она сделает Ваш код более устойчивым, легче поддержать, и более эффективный.
По большему техническому решению, если бы я был в Вашем положении, это было бы моим выбором.
Отчаянные положения призывают к отчаянным мерам. Вы рассмотрели взламывание объектного кода (или файл библиотеки) одной из библиотек, изменив сталкивающийся символ на альтернативное имя - той же длины, но другого написания (но, рекомендация, та же длина имени)? По сути противный.
не ясно, вызывает ли Ваш код непосредственно эти две функции с тем же именем, но различными реализациями или является ли конфликт косвенным (и при этом не ясно, имеет ли это любое значение). Однако существует, по крайней мере, ничтожный шанс, что переименование работало бы. Это могла бы быть идея также для уменьшения различия в написаниях, так, чтобы, если символы находятся в отсортированном порядке в таблице, переименование не перемещало вещи не в порядке. Вещи как двоичный поиск нарушаются, не находится ли массив, который они ищут, в отсортированном порядке как ожидалось.
Вы рассмотрели использование функций времени выполнения (/usr/include/objc/runtime.h) для клонирования одного из конфликтующих классов к не сталкивающемуся классу и затем загрузки сталкивающейся платформы класса? (это потребовало бы, чтобы сталкивающиеся платформы были загружены в разное время для работы.)
можно осмотреть классы ivars, методы (с именами и адресами реализации) и именами со временем выполнения, и создать собственное также динамично, чтобы иметь то же ivar расположение, адреса имен/реализации методов, и только отличаться по имени (для предотвращения коллизии)
Это грубо, но Вы могли использовать распределенные объекты для хранения одного из классов только в зависимом адресе программ и RPC к нему. Это станет грязным, если Вы передадите тонну материала назад и вперед (и может не быть возможным, если оба класса непосредственно управляют представлениями, и т.д.).
существуют другие потенциальные решения, но многие из них зависят от точной ситуации. В частности, Вы использующий современное или время выполнения прежней версии, Вы толстая или единая архитектура, 32 или 64 бита, какие версии ОС - Вы предназначение, являются Вами динамично соединение, статически соединение, или делают у Вас есть выбор, и это потенциально хорошо, чтобы сделать что-то, что могло бы потребовать обслуживания для новых обновлений программного обеспечения.
, Если Вы являетесь действительно отчаянными, что Вы могли сделать:
, Вышеупомянутое будет довольно трудоемким, и если необходимо реализовать его против нескольких archs и различных версий среды выполнения, это будет очень неприятно, но это может определенно быть сделано работать.
Добавление префикса Ваших классов с уникальным префиксом является существенно единственной опцией, но существует несколько способов сделать это менее обременительным и ужасным. Существует долгое обсуждение опций здесь . Мой фаворит @compatibility_alias
директива компилятора Objective C (описал здесь ). Можно использовать @compatibility_alias
для "переименовывания" класса, позволяя Вам назвать Ваш класс с помощью FQDN или некоторого такого префикса:
@interface COM_WHATEVER_ClassName : NSObject
@end
@compatibility_alias ClassName COM_WHATEVER_ClassName
// now ClassName is an alias for COM_WHATEVER_ClassName
@implementation ClassName //OK
//blah
@end
ClassName *myClass; //OK
Как часть полной стратегии, Вы могли снабдить префиксом все свои классы уникальный префикс, такие как FQDN и затем создать заголовок с весь @compatibility_alias
(я предположу, что Вы могли автоматически сгенерировать было, сказано в заголовке).
оборотная сторона добавления префикса как это - то, что необходимо ввести истинное имя класса (например, COM_WHATEVER_ClassName
выше) в чем-либо, чему нужно имя класса от строки помимо компилятора. В частности, @compatibility_alias
директива компилятора, не, функция времени выполнения так NSClassFromString(ClassName)
перестанет работать (возврат nil
) - необходимо будет использовать NSClassFromString(COM_WHATERVER_ClassName)
. Можно использовать ibtool
через фазу разработки для изменения имен классов в Интерфейсном Разработчике nib/xib так, чтобы Вы не писали полный COM_WHATEVER_... в Интерфейсном Разработчике.
Заключительный протест: потому что это - директива компилятора (и неясный в том), это не может быть портативно через компиляторы. В частности, я не знаю, работает ли это с Лязгом frontend из проекта LLVM, хотя это должно работать с LLVM-GCC (LLVM использование GCC frontend).
Кажется, что проблема - то, что Вы не можете сослаться на файлы заголовков от обеих систем в той же единице перевода (исходный файл). Если Вы создаете объективные-c обертки вокруг библиотек (делающий их более применимый в процессе), и только #include заголовки для каждой библиотеки в реализации классов обертки, которые эффективно разделили бы коллизии имени.
у меня нет достаточного опыта с этим в цели-c (просто начинающий), но я верю тому, именно это я сделал бы в C.
Несколько человек уже поделились хитрым и умным кодом, который может помочь решить проблему. Некоторые из предложений могут работать, но все они далеко не идеальны, а некоторые из них совершенно неприятны для реализации. (Иногда уродливые взломы неизбежны, но я стараюсь избегать их, когда могу.) С практической точки зрения вот мои предложения.
I ' я предполагаю, что лицензионные сборы, сроки и сроки могут помешать немедленным действиям по любому из этих пунктов. Надеюсь, вы сможете разрешить конфликт как можно скорее. Удачи!