title: Replace a function pointer in a shared library with ctypes
body: <p>I am trying to replace an existing function pointer in a shared library with a callback defined in Python, through ctypes.</p>
  <p>The source of the shared library in C:</p>
  <pre><code>#include &lt;assert.h&gt;
  #include &lt;stdio.h&gt;
  
  void (*plot)();
  
  int c_main(int argc, void** argv) {
    printf(&quot;plot is %p\n&quot;, (void*)plot);
    assert(plot != NULL);
    plot();
    return 0;
  }
  </code></pre>
  <p>The source of the Python script:</p>
  <pre><code>from sys import platform
  from pathlib import Path
  import ctypes
  import _ctypes
  
  
  FUNCTYPE = ctypes.WINFUNCTYPE if platform == 'win32' else ctypes.CFUNCTYPE
  
  
  def dlclose(obj):
      if platform == &quot;win32&quot;:
          _ctypes.FreeLibrary(obj._handle)
      else:
          _ctypes.dlclose(obj._handle)
  
  
  def enc_args(args):
      C_ARGS = (ctypes.POINTER(ctypes.c_char) * len(args))()
      for idx, arg in enumerate(args):
          C_ARGS[idx] = ctypes.create_string_buffer(arg.encode(&quot;utf-8&quot;))
      return C_ARGS
  
  
  @FUNCTYPE(None)
  def plotxy():
      print(&quot;plotxy&quot;)
  
  
  C_ARGS = enc_args([str(Path(__file__))])
  CAUXDLL = ctypes.CDLL(&quot;./test.so&quot;)
  
  print(plotxy)
  
  print(CAUXDLL.plot)
  
  CAUXDLL.plot = plotxy
  
  print(CAUXDLL.plot)
  
  print(CAUXDLL.c_main(len(C_ARGS), C_ARGS))
  </code></pre>
  <p>The script to test it:</p>
  <pre><code>gcc -fPIC -shared -o test.so test.c
  python3 test.py
  </code></pre>
  <p>The output I get:</p>
  <pre><code># ./test.sh
  &lt;CFunctionType object at 0x7fb1f0abb1c0&gt;
  &lt;_FuncPtr object at 0x7fb1f0abb640&gt;
  &lt;CFunctionType object at 0x7fb1f0abb1c0&gt;
  plot is (nil)
  python3: test.c:8: c_main: Assertion `plot != NULL' failed.
  ./test.sh: line 3: 21171 Aborted                 python3 test.py
  </code></pre>
  <p>So, it seems that the function defined in Python (plotxy) is of type <code>CFunctionType</code>, while the function pointer defined in C is of type <code>_FuncPtr</code>. Although the replacement in <code>CAUXDLL</code> is applied, it seems to have no effect when the main function is called.</p>
  <p>Apart from reading <a href="https://docs.python.org/3/library/ctypes.html#module-ctypes" rel="nofollow noreferrer">https://docs.python.org/3/library/ctypes.html#module-ctypes</a>, I found other questions (e.g. <a href="https://stackoverflow.com/questions/56706290/how-to-use-typedef-in-ctypes">How to use typedef in ctypes</a> or <a href="https://stackoverflow.com/questions/62702848/python-cytpes-creating-callback-function-segmentation-fault-core-dumped">python cytpes creating callback function - Segmentation fault (core dumped)</a>), but I cannot find how to convert <code>CFunctionType</code> (plotxy) to <code>_FuncPtr</code>.</p>
  <p><strong>EDIT</strong></p>
  <p>I believe this might not be an issue with the regular usage of ctypes. That's something I have successfully achieved and which is sufficiently explained in the docs. This question goes beyond. I don't want to execute the C function. I want Python to replace an existing function pointer with a callback written in Python. Note that it is possible to do it by using a helper C function (see <a href="https://github.com/ghdl/ghdl-cosim/blob/master/vhpidirect/shared/pycb/caux.c#L32-L40" rel="nofollow noreferrer">https://github.com/ghdl/ghdl-cosim/blob/master/vhpidirect/shared/pycb/caux.c#L32-L40</a>). Hence this question is about how to achieve it without that helper function (if possible).</p>