Understanding repetitions in Swig tutorial example - python

I am new to learning swig. I am interested in calling C++ from Python on an Ubuntu machine.
I just started looking at the intro tutorial here http://www.swig.org/tutorial.html
Consider the interface file on that page example.i copied as is below.
/* example.i */
%module example
%{
/* Put header files here or function declarations like below */
extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();
%}
extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();
Why is are the contents between the %{ %} repeated in the second half of the file? As given in the manual, http://www.swig.org/Doc3.0/SWIGDocumentation.html#Introduction_nn5
The %{ %} block provides a location for inserting additional code,
such as C header files or additional C declarations, into the
generated C wrapper code.
But it doesn't address the point of the repetition in the example. What am I missing?

The code between %{ and %} is inserted verbatim in the generated SWIG wrapper, and is used to give the wrapper code access to the headers or declarations listed.
The code outside those markers instructs SWIG to make a wrapper for each of the declarations (or entire header files) listed.
If you left out extern int fact(int n); in the first portion, the wrapper, when compiled and linked to the source or library containing the function, wouldn't be able to access the function since the extern declaration would be missing. If left out of the second portion, a wrapper wouldn't be generated to access it from the scripting language.
There is a shortcut:
%inline %{
...
%}
That instructs SWIG to both insert and wrap the declarations.

Related

How to wrap C file with extern variables with Cython

I want to wrap a quite long C function published by a scientist with Cython. I am following
http://scipy-lectures.github.io/advanced/interfacing_with_c/interfacing_with_c.html#interfacing-with-c
and I am able to replicate the examples with numpy support.
I am confused about what to do (or to do anything at all) about variables declared as extern in the library.cpp. Obviously, I will have a main.py that will call this function, not a main.cpp. How should I declare ini_flag and A and pass to func? Is there any other way than making them arguments to the function? If possible I would prefer not to edit original library.cpp file.
// main.cpp:
int ini_flag=0, *A;
void main(){
func(...)
...
}
// library.cpp:
extern int ini_flag, *A;
void func(...){
if (ini_flag==0){
// malloc and initialize A
ini_flag=1;
}
// use A and do other stuff
}
You should create a corresponding library.hpp file:
int ini_flag, *A;
void func(...)
And then in Cython:
cdef extern from "library.hpp":
int ini_flag, *A
void func(...)
Then you can then use them normally in Cython.

Using typedef with SWIG

I have a C header file containing structure definitions with typedef, and an array of char definition with typedef too:
/* File: test.h */
typedef struct
{
char *key;
void *value;
int size;
} cti_pair;
typedef char FOO[CONST];
The SWIG interface file contains the following lines:
/* File: test.i */
%module test
%{
#define SWIG_FILE_WITH_INIT
#include "/home/users/jdoe/workspace/project/src/lib-cti/test.h"
...
%}
#ifndef CTI_TYPES_H_
#define CTI_TYPES_H_
#include "cti_const.h"
typedef char FOO[CONST];
typedef struct
{
char *key;
void *value;
int size;
} cti_pair;
The problem is that I can access the cti_pair struct, but can't use FOO (it's not defined) in my python script.
Ok, just figure out what the problem was.
Actually, I used %extend in another part of the interface file. But this keyword can only be used on structures, not on basic typedef (and SWIG does not display any error message if we use %extend the wrong way).
As a matter of fact, FOO was defined. The problem was not related to this at all. Thanks!

Preprocessor macro in SWIG

I'm trying to get SWIG to recognize a simple preprocessor macro that "defines" a new function based on another definition and more complicated function. So, in the C header file I have:
#define FOO 1
#define my_macro_fun(args) my_fun(args,FOO)
SWIG sees and successfully wraps my_fun, but I want it to wrap my_macro_fun instead.
SWIG tries to spot macros that are constants and wrap them, but it won't be able to do anything smart with a macro like that. Fortunately there's an easy work around. Imagine you have the following header file:
#define FOO 1
#define my_macro_fun(args) my_fun(args,FOO)
void my_fun(int a, int b);
You can wrap it like:
%module test
%{
#include "test.h"
%}
%include "test.h"
which skips the my_macro_fun function. To get SWIG to wrap that though all you need to do is:
%module test
%{
#include "test.h"
%}
// Lie! Tell SWIG that it should be wrapped like any other function.
void my_macro_fun(int);
// This is entirely optional: it will cause my_fun to be wrapped as well
%include "test.h"
This little lie is perfectly fine in SWIG - it'll generate Wrapper code that assumes my_macro_fun(int) is callable, exactly like you would if you were using the macro. When compiling the wrapper the compiler will end up using the macro there and nobody is any the wiser.
Note that the order is important - the function that's really a macro needs to come before the %include in the interface file otherwise SWIG will try to expand the macro during the parsing of your declaration which makes for a syntax error. You can skip the %include entirely, or use a %ignore as well if you want to include it for other parts but suppress the original my_fun in the generated interface.
With some SWIG languages (e.g. Python) you can also use the typemap default:
%module test
%{
#include "test.h"
%}
%typemap(default) int b {
$1 = FOO;
}
%include "test.h"
To supply a value for an argument if none is given for it.

Creating swig wrapper for C++ (pointers) to python

I a very new to swig and I am trying to create a swig wrapper in order to use a few C++ files in python. I have the following C++ class.
The following is a snippet of the code that I am trying to convert:
/*packet_buffer.h*/
class CPacketBuffer {
public:
// construct based on given buffer, data is not copied
CPacketBuffer(uint8_t* data, uint32_t length) {
mpBuffer = data;
mLength = length;
mHead = 0;
mTail = length;
}
uint8_t* GetBuffer() {
return (mpBuffer + mHead);
}
void Add(const uint8_t* data, uint32_t length) {
if ((mTail + length) > mLength) {
length = (mLength - mTail);
}
//....
}
I have been trying to write a example.i file that would accept pointers to typedefs(uint8_t *) all day today using help from swig documentation, but I have been unsuccessful.
The following is a packet_buffer.i file that I have tried which doesn't work.
%module packet_buffer
%include typemaps.i
%apply unsigned char* {uint8_t*};
%apply unit8_t *INPUT {uint8_t *data};
%{
#define SWIG_FILE_WITH_INIT
#include "../include/packet_buffer.h"
%}
%include "../include/packet_buffer.h"
How do I write a swig code for member functions that take pointers to typedefs?
Can I write a common %apply that can be used across the code or will I have to write specifics for each INPUT, OUTPUT parameter?
If I've understood this correctly the problem you're facing isn't that they're pointers, it's that they're potentially unbounded arrays.
You can warp an unbounded C array using carrays.i and the "%array_class" macro, e.g.:
%module packet
%include "stdint.i"
%{
#include "packet.h"
%}
%include "carrays.i"
%array_class(uint8_t, buffer);
%include "packet.h"
Would then allow you to in Python write something like:
a = packet.buffer(10000000)
p = packet.CPacketBuffer(a.cast(), 10000000)
Note that you'll need to ensure the life of the buffer is sufficient - if the Python object gets released without the C++ code being aware you'll end up with undefined behaviour.
You can convert uint8_t* pointers (unbounded arrays) to buffer instances in Python using the frompointer methods that the %array_class macro also creates, e.g.:
r = packet.GetBuffer()
buf = packet.buffer_frompointer(r)
You can add additional Python code to automate/hide most of the conversion between buffers if desired, or use MemoryViews to integrate tighter with Python on the C API side.
In general though since this is C++ I'd suggest using std::vector for this - it's much nicer to use on the Python side than the unbounded arrays and the cost is minimal for the safety and simplicity it gives you.

%rename and %inline in swig, error checking

I use SWIG and Numpy. I define a C function called inplace() to process data array fast, and I want to make some error checking (if two arrays have the same dimentions).
I use %rename and %inline in the .i file. As I understand, rename should map the function names', so every time someone uses inplace, safe_inplace is run and the errors are checked.
But it does not work :( . As far I notice, safe_inplace is not executed, python runs directly inplace without touching the safe version of the function.
# .i
%include "inplace.h"
%rename (inplace) safe_inplace;
%inline %{
void safe_inplace(int* datain, int in_dx, int in_dy, int in_dz,
int* dataout, int out_dx, int out_dy)
{
if ((in_dx != out_dx) || (in_dy != out_dy)) {
PyErr_Format(PyExc_ValueError, /*... messgage*/)
return;
}
inplace( /* .. pass the arguments to original function*/ );
}
header file:
# .h
void inplace(int* datain, int in_dx, int in_dy, int in_dz, int* dataout, int out_dx, int out_dy);
Python:
#.py
inplace.inplace(a,b)
The original example that I modify can be found here
Your original approach was close, but you probably want to get SWIG not to wrap the original version of the function at all.
I've put together a slightly simpler example illustrating how this could work. Given the header file:
void foo();
We want to wrap it such that a slightly modified version is called before invoking the real one.
The simplest way to do this would be to never actually show SWIG the header file at all for wrapping, only for compiling the wrapper, e.g.:
%module test
%{
#include "test.h"
#include <iostream>
%}
%rename (foo) foo_safe;
%inline %{
void foo_safe() {
std::cout << "Hello world" << std::endl;
foo(); // Calls the foo() from test.h, as you'd hope
}
%}
If you don't want to drop the %include (e.g. there's other things you care about in that header file too) you can do something like:
%module test
%{
#include "test.h"
#include <iostream>
%}
%rename (unsafe_foo) foo;
%include "test.h"
%rename (foo) foo_safe;
%inline %{
void foo_safe() {
std::cout << "Hello world" << std::endl;
foo();
}
%}
To expose the real implementation of foo as unsafe_foo.
Or you could use %ignore if there's no reason for Python users to be able to call unsafe_ignore ever:
%module test
%{
#include "test.h"
#include <iostream>
%}
%rename (foo) foo_safe;
%inline %{
void foo_safe() {
std::cout << "Hello world" << std::endl;
foo();
}
%}
%ignore foo;
%include "test.h"
Finally it looks like your goal is actually just to run some code prior to the call of the real C function. If that's the case there's a few ways you can do that too, for example you can add python code before the real function call is made with pythonprepend:
%feature("pythonprepend") foo() %{
print "hello world"
# check args and raise possibly
%}
Or lastly you could use the %exception functionality too, something like (untested):
%exception inplace {
// Check args and possibly throw
$action
}
$action will be substituted with the real call automatically.

Categories