0
votes

I am creating a Python wrapper for an existing code base with a DLL and header. I am using SWIG.

The code base has multiple struct pointer defs like so:

typedef struct session* session_t;

In this example, session is not defined anywhere else. All other functions in the DLL take session_t as an input. If I try and reference session anywhere in SWIG generated code I get compile errors that session is not defined. I need a way to access the value of session_t in Python code.

I've tried using cpointer.i and pointer_functions macro, but this doesn't work since it assumes the input type is not a pointer.

I thought if I could redefine the struct:

typedef struct Session {} session, *session_t;

This could work, but I cant find a way to do this with SWIG.

Is there a way to access the value of a struct pointer with SWIG if it's only definition is a typdef struct pointer?

Edit: possible fix is the SWIG %ignore directive. Might be able to ignore the original struct def and replace it in the .i file.

Solved(ish): I marked Mark Tolonen's answer as correct since it has a lot of useful relevant information. The API I'm trying to wrap has a lot of deleted constructors and behaviors locking down how it's used. I ended up writing a C++ wrapper in it's own namespace then telling Swig to ignore everything except my namespace. I then only use standard or my own types to interface with Swig/Python.

1
A possible workaround is to complete the structure declaration, e.g. put struct session {}; somewhere in the header file. This way, you must also ensure that you never allocate a struct session by yourself.minmaxavg
You need a factory function like session_t session_open(void) which returns a new instance of session_t (like e.g. fopen).Henri Menke
I anticipate that you have some function, which creates a session* and perhaps other functions, which use session*. Take a lot at this answer, stackoverflow.com/questions/32478649/… The base class can be replaced with a simple typedef to make it more C likeJens Munk

1 Answers

2
votes

SWIG works very well with opaque types. Here's a full example where I've provided the source for a test.dll that uses an opaque typedef. The structure is only defined within the .c file and SWIG has no knowledge of the definition. If you are still having a problem update your question with a reproducible example. I suspect you've used session instead of session_t in some typemap, but without a reproducible example I can only show that it works without a definition.

test.c

#define API_EXPORTS
#include <stdlib.h>
#include "test.h"

struct session {
    int a;
};

API session_t alloc(void) {
    session_t s = malloc(sizeof(session_t));
    if(s)
        s->a = 123;
    return s;
}

API int get_a(session_t s) {
    return s->a;
}

API void release(session_t s) {
    free(s);
}

test.h

#ifdef API_EXPORTS
#   define API __declspec(dllexport)
#else
#   define API __declspec(dllimport)
#endif

typedef struct session* session_t;

API session_t alloc(void);
API int get_a(session_t s);
API void release(session_t session);

test.i

%module test
%{
#include "test.h"
%}

%include <windows.i>
%include "test.h"

test session

Python 2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:19:30) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> s = test.alloc()
>>> test.get_a(s)
123
>>> test.release(s)
>>>