Multiple byte "OUTPUT" arguments in SWIG?

52 views Asked by At

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 INPUT parameters allow integer values to be passed instead of pointers and how the OUTPUT parameter creates a return result.

If you don't want to use the names INPUT or OUTPUT, 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]'
1

There are 1 answers

0
Criminal_Affair_At_SO On

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.i typemaps.

This answer has an example: Pass Python bytes to C/C++ function using swig?