I've got a C library which has 3 functions (all arguments are fixed-length uint8_t*, with the length known at compile time):
- One which has 2 output parameters only
- One which has 1 input parameter and 2 output parameters
- One which has 2 input parameters and 1 output parameter
I'm trying to create SWIG-based Python bindings for this C library, but they don't seem to work. Even after importing typemaps.i, swig still complains that a bytearray is inappropriate for a uint8_t INOUT[] argument when trying to call the function.
I don't get it. What am I doing wrong?
https://www.swig.org/Doc4.1/Python.html#Python_nn46
Notice how the
INPUTparameters allow integer values to be passed instead of pointers and how theOUTPUTparameter creates a return result.If you don't want to use the names
INPUTorOUTPUT, use the %apply directive.
It doesn't look like %pybuffer_mutable_binary is the right choice, since it requires a size parameter, and my interface doesn't have one.
Appendix: code
SWIG module
%module "libmceliece6960119f_clean"
%include "typemaps.i"
%{
// https://github.com/PQClean/PQClean/blob/fb003a2a625c49f3090eec546b2383dcfa2c75d8/crypto_kem/mceliece6960119f/clean/api.h
#include "api.h"
%}
int PQCLEAN_MCELIECE6960119F_CLEAN_crypto_kem_keypair(
uint8_t INOUT[PQCLEAN_MCELIECE6960119F_CLEAN_CRYPTO_PUBLICKEYBYTES],
uint8_t INOUT[PQCLEAN_MCELIECE6960119F_CLEAN_CRYPTO_SECRETKEYBYTES]);
int PQCLEAN_MCELIECE6960119F_CLEAN_crypto_kem_enc(
uint8_t INOUT[PQCLEAN_MCELIECE6960119F_CLEAN_CRYPTO_CIPHERTEXTBYTES],
uint8_t INOUT[PQCLEAN_MCELIECE6960119F_CLEAN_CRYPTO_BYTES],
const uint8_t INPUT[PQCLEAN_MCELIECE6960119F_CLEAN_CRYPTO_PUBLICKEYBYTES]);
int PQCLEAN_MCELIECE6960119F_CLEAN_crypto_kem_dec(
uint8_t INOUT[PQCLEAN_MCELIECE6960119F_CLEAN_CRYPTO_BYTES],
const uint8_t INPUT[PQCLEAN_MCELIECE6960119F_CLEAN_CRYPTO_CIPHERTEXTBYTES],
const uint8_t INPUT[PQCLEAN_MCELIECE6960119F_CLEAN_CRYPTO_SECRETKEYBYTES]);
Usage (broken)
_libmceliece6960119f_clean.PQCLEAN_MCELIECE6960119F_CLEAN_crypto_kem_keypair()
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# TypeError: PQCLEAN_MCELIECE6960119F_CLEAN_crypto_kem_keypair expected 2 arguments, got 0
pk, sk = bytearray(1047319), bytearray(13948); _libmceliece6960119f_clean.PQCLEAN_MCELIECE6960119F_CLEAN_crypto_kem_keypair(pk, sk)
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# TypeError: in method 'PQCLEAN_MCELIECE6960119F_CLEAN_crypto_kem_keypair', argument 1 of type 'uint8_t [PQCLEAN_MCELIECE6960119F_CLEAN_CRYPTO_PUBLICKEYBYTES]'
You haven't created a typemap, you need a typemap.
There are examples for this typemap in the SWIG documentation, you should use the
pybuffer.itypemaps.This answer has an example: Pass Python bytes to C/C++ function using swig?