Использование макросов препроцессора для определения примитивных значений в качестве аргументов функции с помощью SWIG

#c #swig

Вопрос:

Допустим, у меня в коде на C есть следующий макрос:

 #if __SOME_CONDITION__
#define SAMPLE_TYPE double
#elif
#define SAMPLE_TYPE float
#endif
 

который в основном определяет SAMPLE_TYPE один из двух возможных типов примитивов в зависимости от другой директивы компилятора/другого определения препроцессора.

У меня есть следующий заголовок для класса, который я обертываю с помощью SWIG:

 class SomethingStatic {
    public:
        static SAMPLE_TYPE someFunction();
}
 

когда я создаю и обертываю код и ссылку SomethingStatic.someFunction из своего кода Java, тип возвращаемого значения задается как SWIGTYPE_p_SAMPLE_TYPE , который также был сгенерирован SWIG.

Как я могу настроить SWIG для возврата примитива float или double значения, которое оценивает макрос?

Комментарии:

1. Я не знаю, сработает ли это, но SWIG мог бы понять, что вы делаете лучше, если бы вы использовали typedefs вместо #defines.

2. @zwol, к сожалению, он обеспечивает то же поведение, что и typedef.

3. Предварительно обработайте код, прежде чем позволить SWIG его увидеть? Возможно, не лучший способ, но это то, что сразу приходит на ум.

4. Прошло довольно много времени с тех пор, как я использовал #define или typedef для обработки примитивных типов. Сегодня я использую шаблоны, и здесь SWIG всегда обрабатывает их правильно. Недостатком является то, что вам необходимо явно создавать экземпляры ваших шаблонов, используя %template синтаксис

5. Это должно сработать нормально. Убедитесь, что заголовок определения SAMPLE_TYPE непосредственно %include отредактирован в .i файле. По умолчанию SWIG не рекурсирует в файлы заголовков.

Ответ №1:

SWIG понимает препроцессор, но вы должны %include использовать заголовок с прямым определением. SWIG не рекурсирует в другие заголовки, включенные в заголовок. Также не забудьте объявить значения препроцессора при вызове swig , а также компилятора.

Пример:

состояние.h

 #ifdef CONDITION
#define SAMPLE_TYPE double
#else
#define SAMPLE_TYPE int
#endif
 

класс.h

 #include "condition.h"

class SomethingStatic {
public:
    static SAMPLE_TYPE someFunction() {
    #ifdef CONDITION
        return 1.5;
    #else
        return 2;
    #endif
    }
};
 

test.i

 %module test

// This code is directly included in the wrapper.
// C   will process condition.h implicitly
%{
#include "class.h"
%}

// Headers that SWIG will create wrappers for.
// SWIG *does not* recurse into subheaders by default.

%include "condition.h" // must be explicit with SWIG
%include "class.h"
%}
 

Использование «swig -python -c test.i» и компиляция без /DCONDITION:

 >>> import test
>>> x=test.SomethingStatic()
>>> x.someFunction()
2
 

Использование «swig -DCONDITION -python -c test.i» и компиляция с /DCONDITION:

 >>> import test
>>> x=test.SomethingStatic()
>>> x.someFunction()
1.5
 

Демонстрация, если вы закомментируете %include "condition.h" строку, которая, по-видимому, является первоначальной проблемой операции:

 >>> import test
>>> x=test.SomethingStatic()
>>> x.someFunction()
<Swig Object of type 'SAMPLE_TYPE *' at 0x000001D369F9B4E0>
 

Комментарии:

1. Вот и все! Указав заголовок в разделе %include файла интерфейса, я заставил его работать должным образом. Оглядываясь назад, это имеет смысл, но я совершенно упустил из виду, что определения находились внутри файла, на который ссылались только в коде C, а не через SWIG. Спасибо!