Skip to content

Instantly share code, notes, and snippets.

@sterin
Last active September 7, 2021 19:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save sterin/32b5c7c42a177dacf455 to your computer and use it in GitHub Desktop.
Save sterin/32b5c7c42a177dacf455 to your computer and use it in GitHub Desktop.

Instructions for Linux

Requires SWIG, CMake version 3.8 and above (the SWIG module has changed in 3.8, so previous verions will require a few minor modiciations)

  1. Create a build directory and make it the current dir
mkdir build
cd build
  1. Configure
cmake ..
  1. Build
cmake --build .
  1. Test
ctest
cmake_minimum_required(VERSION 3.8)
project(dummy)
find_package(PythonLibs 3 REQUIRED)
find_package(PythonInterp ${PYTHONLIBS_VERSION_STRING} REQUIRED)
find_package(SWIG REQUIRED)
include(${SWIG_USE_FILE})
if(PYTHONLIBS_VERSION_STRING MATCHES "^2.*$" )
set(CMAKE_SWIG_FLAGS -classic)
else()
set(CMAKE_SWIG_FLAGS -py3)
endif()
message("PYTHONLIBS_VERSION_STRING: ${PYTHONLIBS_VERSION_STRING}")
message("CMAKE_SWIG_FLAGS: ${CMAKE_SWIG_FLAGS}")
include_directories(example ${PYTHON_INCLUDE_PATH} ${CMAKE_CURRENT_SOURCE_DIR})
set_source_files_properties(example.i PROPERTIES CPLUSPLUS ON)
swig_add_library(example TYPE SHARED LANGUAGE python SOURCES example.i)
swig_link_libraries(example ${PYTHON_LIBRARIES})
enable_testing()
add_test(test1 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_example_wrapper.py)
%module example
// a typemap for the callback, it expects the argument to be an integer
// whose value is the address of an appropriate callback function
%typemap(in) void (*f)(int, const char*) {
$1 = (void (*)(int i, const char*))PyLong_AsVoidPtr($input);;
}
%{
void use_callback(void (*f)(int i, const char* str));
%}
%inline
%{
// a C function that accepts a callback
void use_callback(void (*f)(int i, const char* str))
{
f(100, "callback arg");
}
%}
%pythoncode
%{
import ctypes
# a ctypes callback prototype
py_callback_type = ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_char_p)
def use_callback(py_callback):
# wrap the python callback with a ctypes function pointer
f = py_callback_type(py_callback)
# get the function pointer of the ctypes wrapper by casting it to void* and taking its value
f_ptr = ctypes.cast(f, ctypes.c_void_p).value
_example.use_callback(f_ptr)
%}
import example
# python callback
def py_callback(i, s):
print('py_callback(%d, %s)'%(i, s))
example.use_callback(py_callback)
# add the location of the compiled module is in the module search path
import sys
sys.path.append('.')
# run the actual example
import test_example
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment