Skip to content

Call to undeclared library function 'memset', Pyodide support #179

Closed

Description

@HexDecimal

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.

https://github.com/libtcod/python-tcod/actions/runs/15768029104/job/44447935001

  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.

Activity

  1. mattip commented on Jun 20, 2025

    @mattip
    Contributor

    I think this happens from

    • 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
      

    Are you using the limited API?

  2. HexDecimal commented on Jun 20, 2025

    @HexDecimal
    Author

    Are you using the limited API?

    Yes, I am using the Limited API. I'll see what happens when I disable it.

  3. HexDecimal commented on Jun 20, 2025

    @HexDecimal
    Author

    Disabling the limited API fixes the issue with memset.

  4. mattip commented on Jun 20, 2025

    @mattip
    Contributor

    Right, so probably need to review the places we have #include <Python.h> and add a #include <string.h>, like here

    #include <Python.h>
    #ifdef __cplusplus
    extern "C" {
    #endif
    #include <stddef.h>

    and here

    #include <Python.h>
    #include <stddef.h>

  5. HexDecimal commented on Jun 20, 2025

    @HexDecimal
    Author

    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.

  6. mattip commented on Jun 25, 2025

    @mattip
    Contributor

    Hmm. Maybe PYODIDE or some other marker should be defined by default when using CFFI on that platform?

  7. HexDecimal commented on Jun 25, 2025

    @HexDecimal
    Author

    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 = 0x03100000
    define_macros: list[tuple[str, Any]] = []  # For ffi_builder.set_source
    
    if "PYODIDE" not in os.environ:  # Current workaround
        define_macros.append(("Py_LIMITED_API", Py_LIMITED_API))  # Explicitly setting Py_LIMITED_API on regular builds
  8. mattip commented on Feb 4, 2026

    @mattip
    Contributor

    Closed by #225

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions