mandesero
mandesero

Reputation: 1

Error importing WebAssembly function in CPython build

I am building CPython with WebAssembly using WASI-SDK-24.0 and the wasmtime runtime. My goal is to expose WebAssembly network functions, such as sock_addr_local, to CPython.

Issue

When I run CPython with the following command:

/cross-build/wasm32-wasi/python.sh

I get this error when calling sock_addr_local from Python:

Python 3.14.0a1+ (heads/main-dirty:759a54d28ff, Oct 22 2024, 10:57:25) [Clang 18.1.2-wasi-sdk ...]
>>> import sys, wasimodule
>>> sys.platform
'wasi'
>>> wasimodule.sock_addr_local(0, 0)
Error: failed to run main module `/home/mandesero/cpython/cross-build/wasm32-wasi/python.wasm`

Caused by:
    0: failed to invoke command default
    1: error while executing at wasm backtrace:
           0: 0x5c42 - python.wasm!undefined_weak:__imported_wasi_snapshot_preview1_sock_addr_local
1: 0x39bf8d - python.wasm!py_sock_addr_local
           2: 0xb438b - python.wasm!cfunction_call
           ...
          34: 0x5c76 - python.wasm!_start
    2: wasm trap: wasm `unreachable` instruction executed

Question

Why am I getting an undefined_weak error for sock_addr_local, and how can I correctly import this function from WASI into CPython? Is there a way to ensure sock_addr_local is correctly linked, or am I missing a setup step for the WASI module in the wasmtime runtime?

Here’s what I’ve done:

Code

In wasmsocketmodule.h, I declared the function as follows:

// wasmsocketmodule.h

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

extern int32_t
__imported_wasi_snapshot_preview1_sock_addr_local(int32_t arg0, int32_t arg1)
__attribute__((
        weak,
        __import_module__("wasi_snapshot_preview1"),
        __import_name__("sock_addr_local")
));

#ifdef __cplusplus
}
#endif

In wasmsocketmodule.c, I created a Python wrapper function:

// wasmsocketmodule.c

#include <Python.h>
#include "wasmsocketmodule.h"

static PyObject* py_sock_addr_local(PyObject* self, PyObject* args) {
    int32_t arg0, arg1;

    if (!PyArg_ParseTuple(args, "ii", &arg0, &arg1)) {
        return NULL;
    }

    int32_t result = __imported_wasi_snapshot_preview1_sock_addr_local(arg0, arg1);
    return PyLong_FromLong(result);
}

static PyMethodDef WasmMethods[] = {
    {"sock_addr_local", py_sock_addr_local, METH_VARARGS, "Get the local socket address."},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef wasimodule = {
    PyModuleDef_HEAD_INIT,
    "wasimodule",
    NULL,
    -1,
    WasmMethods
};

PyMODINIT_FUNC
PyInit_wasimodule(void) {
    return PyModule_Create(&wasimodule);
}

I added wasimodule wasmsocketmodule.c to Modules/Setup.bootstrap.in and built CPython using:

./Tools/wasm/wasm_build.py build

Upvotes: 0

Views: 28

Answers (0)

Related Questions