DLL-оболочка для Python: фатальная ошибка LNK1127: библиотека повреждена

Краткое описание

У меня есть DLL, запрограммированная в ADA с помощью GNAT. Я хочу скомпилировать с MSVC другую DLL на C в качестве оболочки для ADA_DLL, чтобы использовать ее с Python.

Я скомпилировал ada_DLL, затем сгенерировал файл .lib в соответствии с документацию gnat о MSVC. И, наконец, я попытался скомпилировать C_DLL с помощью Visual Studio, получив ошибку:

libmath.lib : fatal error LNK1127: library is corrupt

Обновление: в случае компиляции с помощью gcc, предложенного @Brian, я получаю следующий вывод:

>"C:\GNAT\2015\bin\gcc.exe" -c      -IC:\Python27\include -o libmath_c.o libmath_c.c
>"C:\GNAT\2015\bin\gcc.exe" -shared -LC:\Python27\libs -L./ -l libmath -o DIVISION_CPP.pyd libmath_c.o -lpython27
    .//libmath.lib: error adding symbols: Malformed archive
collect2.exe: error: ld returned 1 exit status

Что я пробовал и больше данных:

Я попытался импортировать ADA_DLL напрямую с ctypes в Python, и это работает, поэтому я считаю, что ADA_DLL правильно скомпилирована. Кроме того, забывать о C_DLL на самом деле не вариант.

Я сделал небольшой пример с модулем примера деления. Мой файл .def выглядит примерно так:

; dlltool -z libmath.def --export-all-symbols libmath.dll
EXPORTS
   [...]
    div @ 259
   [...]

libmath_c.c:

#include "libmath_c.h"
    PyObject* _wrap_DIVISION(PyObject *self, PyObject *args){
       div(10, 2);
       return Py_None;
    }
    __declspec(dllexport) void __cdecl initDIVISION_CPP(void){
       Py_InitModule("DIVISION_CPP", LIB_METHODS_methods);
      }

libmath_c.h:

#include <windows.h>
#include <stdio.h>
#include <Python.h>
PyObject* _wrap_DIVISION(PyObject *self, PyObject *args);
static PyMethodDef LIB_METHODS_methods[] = {
   { "CPP_DIVISION", _wrap_DIVISION, METH_VARARGS },
   {NULL, NULL, 0, NULL}   //Added as indicated by @Brian. Thanks! 
};
__declspec(dllexport) void __cdecl initDIVISION_CPP(void);

Любая идея о том, что происходит? Любая помощь могла бы быть полезна. Спасибо!


person gccinac    schedule 09.11.2016    source источник
comment
Есть ли шанс, что вы можете сделать пример MCVE? Я думаю, что для этого потребуется исходный код Ada (только реализация подразделения), предположительно, клиент Python и команды сборки/Makefile. Кроме того, будет ли работать сборка C DLL в той же версии gcc, что и Gnat, и только использовать ее через MSVC?   -  person user_1818839    schedule 09.11.2016
comment
У меня есть несколько заголовочных файлов Python. Как лучше всего загрузить MCVE с таким количеством стандартных файлов заголовков? Да, использование gcc было бы еще одним вариантом, я попробую и опубликую результаты. Спасибо!   -  person gccinac    schedule 09.11.2016
comment
gcc, возможно, стоит попробовать: даже если он выдает ту же ошибку только с кодом C, который может помочь найти исправление. Кроме того, как (куда) вы звоните adainit() и adafinal()?   -  person user_1818839    schedule 09.11.2016
comment
Спасибо @Брайан! Он скомпилирован с помощью gcc, хотя я получаю import DIVISION_CPP: ValueError: функции модуля не могут устанавливать METH_CLASS или METH_STATIC. Обязательно ли вызывать adainit/adafinal в коде c? В моем (унаследованном) коде ничего подобного не было. Это как-то связано с этим?   -  person gccinac    schedule 09.11.2016
comment
Я не разбираюсь в adainit и т. д.; это может произойти автоматически как часть инфраструктуры DLL... или нет... насколько я знаю, поэтому я поднял это как один из вопросов, на который стоит обратить внимание. Но в любом случае это не связано с ошибкой METH_CLASS.   -  person user_1818839    schedule 09.11.2016


Ответы (2)


Преамбула: Приносим извинения, если это окажется неответом; Я хочу иметь возможность вернуться к этому и снова найти ссылки, а комментарии имеют свойство гнить...

Во-первых, gcc (в версии, совпадающей с Gnat) может работать как альтернативный компилятор C, и если это так, то это может устранить трудности с несовместимыми версиями библиотек.

GCC можно использовать для создания библиотек DLL Windows, поэтому результат можно использовать из других исполняемых файлов Windows.

После комментариев; gcc действительно допускает компиляцию, но результат в настоящее время нельзя использовать с Python — здесь мои знания Python невелики, и у нас нет MCVE, так что это спекулятивно:

В этом разделе вопросов и ответов рассматривается одно и то же сообщение об ошибке между Python и чистым C, без Ada, предполагая, что эта ошибка не может быть специфичной для Ada, обернутой в C.

Вы уже обошли конкретную ошибку спрашивающего,

static PyMethodDef* _npfindmethods = { ... };

который использовал указатель; вы (правильно согласно ответу) статически выделяете массив. Однако принятый ответ завершает список методов

static PyMethodDef _npfindmethods[] = {
    {"add", py_add, METH_VARARGS, py_add_doc},
    {NULL, NULL, 0, NULL}
};

с методом NULL; в вашем примере нет:

static PyMethodDef LIB_METHODS_methods[] = {
   { "CPP_DIVISION", _wrap_DIVISION, METH_VARARGS }
};

Итак, моя гипотеза состоит в том, что когда вы запускаете setup() на этом модуле, он успешно находит CPP_DIVISION, а затем, в отсутствие метода NULL, он убегает в сорняки, создавая те же симптомы, несмотря на разницу в причине.

Я мог бы проверить эту гипотезу, используя MCVE в этом вопросе, удалив метод NULL; однако у меня нет под рукой системы Windows, только Linux.

В качестве альтернативы я не вижу причин для уровня C. Если его нет, эти вопросы и ответы посвящены прямому взаимодействию между Python и Ada. без слоя C, хотя, похоже, он использует другой метод, getattr() для импорта внешнего метода. Может есть альтернатива?

person user_1818839    schedule 09.11.2016
comment
Вы были правы в гипотезе {NULL, NULL, 0, NULL}! :) Я изменю это в своем вопросе, так как теперь я получаю .//libmath.lib: ошибка добавления символов: искаженный архив с gcc, аналогичный исходной ошибке с компилятором MS. - person gccinac; 10.11.2016
comment
Я думаю, что создание MCVE должно быть следующим шагом — возможно, вы можете использовать связанный вопрос в качестве отправной точки и добавить к нему компонент Ada. - person user_1818839; 10.11.2016

Наконец мне удалось скомпилировать с gcc+gnat, но не с MSVC+gnat.

С gcc+gnat я получал .//libmath.lib: ошибка добавления символов: искаженный архив. Решение состоит в использовании libmath.dll вместо сборки .lib из .dll.

Итак, резюмируя:

  • Если у вас есть .dll, сгенерированный gnat, используйте его с gcc. Вам не нужно создавать .lib.
  • Если у вас есть .lib (например, python27.lib) или .dll, не сгенерированный gnat, конвертируйте его в .a с помощью такого инструмента, как «pexport» (НЕ ИСПОЛЬЗУЙТЕ SED!).
  • Если вам действительно нужно скомпилировать с помощью MSVC... Извините, у меня не получилось заставить его работать. Ваша принцесса в другом замке.
person gccinac    schedule 15.11.2016