You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Call to undeclared library function 'memset', Pyodide support #179
When trying to see if my library can be built using Pyodide I encountered a relatively minor issue: memset is from <string.h> which is not included in the source file. There were no other warnings or errors caused by cffi. I tested the latest stable version and main with no differences between them.
build/temp.emscripten_3_1_58_wasm32-cpython-312/tcod._libtcod.c:520:5: error: call to undeclared library function 'memset' with type 'void *(void *, int, unsigned long)'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
520 | memset((void *)p, 0, (size_t)datasize);
| ^
build/temp.emscripten_3_1_58_wasm32-cpython-312/tcod._libtcod.c:520:5: note: include the header <string.h> or explicitly provide a declaration for 'memset'
I would've added #include <string.h> into ffi_builder.set_source but the error happens before the inserted code. I'm also unable to suppress or ignore this error.
I may be able to make a PR for this. My goal is to have a CFFI out-of-line API mode project successfully build for Pyodide in cibuildwheel. I can test PR's and branches.
memset is used in the generated code before code included via set_source
The generated code does include "Python.h", which has this (at least for Python3.11):
// stdlib.h, stdio.h, errno.h and string.h headers are not used by Python
// headers, but kept for backward compatibility. They are excluded from the
// limited C API of Python 3.11.
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
# include <stdlib.h>
# include <stdio.h> // FILE*
# include <errno.h> // errno
# include <string.h> // memcpy()
#endif
Specifically the Py_LIMITED_API definition was directly from my own build scripts to ensure that the limited API was enabled. I can use "PYODIDE" in os.environ to conditionally skip this definition without affecting other platforms.
I now have working Pyodide wheels, or at least they compile. It's easy enough for me to reproduce and check the issue with any new cffi revision.
The PYODIDE environment marker is set by Pyodide during package setup/build to indicate that the package is being built for Emscripten (because sys.platform can not be "emscripten" unless the script is actually running on the platform, not during cross-compilation). https://pyodide.org/en/stable/usage/faq.html#how-to-detect-that-code-is-run-with-pyodide
To be extra clear, this is that my build code looks like:
Py_LIMITED_API=0x03100000define_macros: list[tuple[str, Any]] = [] # For ffi_builder.set_sourceif"PYODIDE"notinos.environ: # Current workarounddefine_macros.append(("Py_LIMITED_API", Py_LIMITED_API)) # Explicitly setting Py_LIMITED_API on regular builds
Activity
mattip commentedon Jun 20, 2025
I think this happens from
memsetis used in the generated code before code included viaset_sourceAre you using the limited API?
HexDecimal commentedon Jun 20, 2025
Yes, I am using the Limited API. I'll see what happens when I disable it.
HexDecimal commentedon Jun 20, 2025
Disabling the limited API fixes the issue with
memset.mattip commentedon Jun 20, 2025
Right, so probably need to review the places we have
#include <Python.h>and add a#include <string.h>, like herecffi/src/cffi/_cffi_include.h
Lines 57 to 61 in 92645ec
and here
cffi/src/cffi/vengine_cpy.py
Lines 819 to 820 in 92645ec
HexDecimal commentedon Jun 20, 2025
Specifically the
Py_LIMITED_APIdefinition was directly from my own build scripts to ensure that the limited API was enabled. I can use"PYODIDE" in os.environto conditionally skip this definition without affecting other platforms.I now have working Pyodide wheels, or at least they compile. It's easy enough for me to reproduce and check the issue with any new cffi revision.
mattip commentedon Jun 25, 2025
Hmm. Maybe
PYODIDEor some other marker should be defined by default when using CFFI on that platform?HexDecimal commentedon Jun 25, 2025
The
PYODIDEenvironment marker is set by Pyodide during package setup/build to indicate that the package is being built for Emscripten (becausesys.platformcan not be"emscripten"unless the script is actually running on the platform, not during cross-compilation).https://pyodide.org/en/stable/usage/faq.html#how-to-detect-that-code-is-run-with-pyodide
To be extra clear, this is that my build code looks like:
mattip commentedon Feb 4, 2026
Closed by #225