From 5f59a8a1171c4bebdf2b28006db78c7dd3a1a452 Mon Sep 17 00:00:00 2001 From: David Hendriks <davidhendriks93@gmail.com> Date: Mon, 4 Nov 2019 10:38:55 +0000 Subject: [PATCH] created some cython DLL reading, i'm able to fetch the memory adress, but not yet finished with the ptr -> int -> ptr conversion. also updated readme --- README.org | 42 ++++++++++++++++++++++++++++++ README.md => README.org~ | 3 +++ ctypes/compile.sh | 3 ++- ctypes/libmean.so.1 | Bin 7528 -> 7984 bytes ctypes/main.py | 44 ++++++++++++++++++++++++++------ ctypes/mean.c | 19 ++++++++++++++ ctypes/mean.h | 4 ++- python-c-api_solution/demolib.c | 5 +--- 8 files changed, 106 insertions(+), 14 deletions(-) create mode 100644 README.org rename README.md => README.org~ (99%) diff --git a/README.org b/README.org new file mode 100644 index 0000000..e90a45f --- /dev/null +++ b/README.org @@ -0,0 +1,42 @@ +# python-c-interface + +Repo for interfacing python with c. Main goal is to be able to compile a function and give the pointer to that function to a c program. + +# Leads: +# https://stackoverflow.com/questions/17980167/writing-python-ctypes-for-function-pointer-callback-function-in-c +# https://wiki.python.org/moin/IntegratingPythonWithOtherLanguages +# https://cffi.readthedocs.io/en/release-1.4/using.html?highlight=re +# http://www.swig.org/Doc1.3/SWIG.html#SWIG_nn30 +# https://stackoverflow.com/questions/51273804/returning-a-function-python-c-api +# https://docs.scipy.org/doc/numpy/reference/c-api.types-and-structures.html#c.PyArray_ArrFuncs.fillwithscalar +# https://stackoverflow.com/questions/43162622/python-passing-pointers-between-c-and-python-with-ctypes +# https://stackoverflow.com/questions/4213095/python-and-ctypes-how-to-correctly-pass-pointer-to-pointer-into-dll + +# https://stackoverflow.com/questions/41954269/create-c-function-pointers-structure-in-python +# https://stackabuse.com/enhancing-python-with-custom-c-extensions/ Read +# https://stackoverflow.com/questions/49941617/runtime-generation-and-compilation-of-cython-functions +# https://realpython.com/cpython-source-code-guide/ +# https://docs.python.org/3.6/c-api/index.html +# https://stackoverflow.com/questions/6626167/build-a-pyobject-from-a-c-function +# https://docs.python.org/3.6/extending/newtypes_tutorial.html?highlight=pointer +# https://realpython.com/cpython-source-code-guide/ +# https://diseraluca.github.io/blog/2019/03/21/wetting-feet-with-python-c-api +# https://docs.python.org/3/c-api/function.html + +# http://koichitamura.blogspot.com/2008/06/this-is-small-python-capi-tutorial.html +# https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#including-verbatim-c-code probably works too! +# https://www.oreilly.com/library/view/python-cookbook/0596001673/ch16s07.html +# https://stackoverflow.com/questions/53215786/when-writing-a-python-extension-in-c-how-does-one-pass-a-python-function-in-to +# https://pythonextensionpatterns.readthedocs.io/en/latest/refcount.html +# https://bitbucket.org/cffi/cffi/issues/265/cffi-doesnt-allow-creating-pointers-to +# https://stackoverflow.com/questions/40166645/a-c-pointer-passed-between-c-and-python-using-capsule-is-empty +# https://www.youtube.com/watch?v=2B0CMF3cYPA +# https://stackoverflow.com/questions/16993927/using-cython-to-link-python-to-a-shared-library + + +* Current Status: +I managed to compile a shared library on runtime, and also load the function pointer memory adress of a dynamically loaded function. + +** TODO Cast that pointer value into an integer and pass it to another function that will use that int as a function pointer again +** TODO Test within c-script itself +** TODO First in the dummy script, just to try things out, and then in the script where python is the bridge between diff --git a/README.md b/README.org~ similarity index 99% rename from README.md rename to README.org~ index 4ca4a36..879fc71 100644 --- a/README.md +++ b/README.org~ @@ -32,3 +32,6 @@ Repo for interfacing python with c. Main goal is to be able to compile a functio # https://stackoverflow.com/questions/40166645/a-c-pointer-passed-between-c-and-python-using-capsule-is-empty # https://www.youtube.com/watch?v=2B0CMF3cYPA # https://stackoverflow.com/questions/16993927/using-cython-to-link-python-to-a-shared-library + + + diff --git a/ctypes/compile.sh b/ctypes/compile.sh index 736d146..0c12caf 100644 --- a/ctypes/compile.sh +++ b/ctypes/compile.sh @@ -1,2 +1,3 @@ # Compile a shared library -gcc -shared -o libmean.so.1 mean.c \ No newline at end of file +gcc -shared -o libmean.so.1 -fPIC mean.c +gcc -o main -fPIC mean.c \ No newline at end of file diff --git a/ctypes/libmean.so.1 b/ctypes/libmean.so.1 index 1ede0ce64eb59a8cf19dfffde096fbdf7fe4c32d..df6280d836c719bec47c764d75c8a0222edbf955 100755 GIT binary patch literal 7984 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 literal 7528 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 diff --git a/ctypes/main.py b/ctypes/main.py index d5549a5..67ad75a 100644 --- a/ctypes/main.py +++ b/ctypes/main.py @@ -5,6 +5,10 @@ # https://stackoverflow.com/questions/9420673/is-it-possible-to-compile-c-code-using-python # https://documentation.help/Python-3.2.1/ctypes.html + +# https://stackoverflow.com/questions/49635105/ctypes-get-the-actual-address-of-a-c-function + + import ctypes import os import subprocess @@ -14,15 +18,39 @@ def buildLibrary(): # store the return code of the c program(return 0) # and display the output s = subprocess.check_call("bash compile.sh", shell=True) - print("return code:\n{}".format(s)) + if not s==0: + print("return code:\n{}".format(s)) +# Building library buildLibrary() - +# Loading library libmean = ctypes.CDLL("libmean.so.1") # loads the shared library -libmean.mean.restype = ctypes.c_double # define mean function return type -print(libmean.mean) -print(libmean.mean(ctypes.c_double(10), ctypes.c_double(3))) # call mean function needs cast arg types -libmean.mean.argtypes = [ctypes.c_double, ctypes.c_double] # define arguments types -print(libmean.mean(10, 3)) # call mean function does not need cast arg types -print(type(libmean.mean(10, 5))) \ No newline at end of file + +# # +# Pointer +print("Function pointer of the function printing the function pointer: {}".format(libmean.print_pointer_to_mean)) + +# Memory adress +libmean.print_pointer_to_mean() + +# Get memory adress of function. mimicking a pointer +mem = ctypes.cast(libmean.mean, ctypes.c_void_p).value + +# ijij +print("pointer to mean function (via python code): {}".format(mem)) +print("Hex memory adress: {}".format(hex(mem))) +print(type(hex(mem))) + + + + + + + +# Other uses of this code +# print(libmean.mean) +# print(libmean.mean(ctypes.c_double(10), ctypes.c_double(3))) # call mean function needs cast arg types +# libmean.mean.argtypes = [ctypes.c_double, ctypes.c_double] # define arguments types +# print(libmean.mean(10, 3)) # call mean function does not need cast arg types +# print(type(libmean.mean(10, 5))) \ No newline at end of file diff --git a/ctypes/mean.c b/ctypes/mean.c index 12d80b0..31d4667 100644 --- a/ctypes/mean.c +++ b/ctypes/mean.c @@ -1,5 +1,24 @@ #include "mean.h" +#include <stdio.h> +#include <stdlib.h> double mean(double a, double b) { + printf("calculating mean with %f and %f", a, b); return (a+b)/2; +} + +void print_pointer_to_mean() { + printf("pointer to mean function (via c code): %p\n", &mean); +} + +double calc_mean_using_pointer(double (*pf)(double, double), double number_1, double number_2) { + double result; + result = pf(number_1, number_2); + printf("result running mean function with pointer to the function: %f", result); + return result; +} + +void main() { + double res = double mean(double 3.1, double 6.2); + printf("result %f", res); } \ No newline at end of file diff --git a/ctypes/mean.h b/ctypes/mean.h index a52ef61..3fdc9b1 100644 --- a/ctypes/mean.h +++ b/ctypes/mean.h @@ -1,3 +1,5 @@ // Returns the mean of passed parameters -double mean(double, double); \ No newline at end of file +double mean(double, double); +void print_pointer_to_get_value(); +double calc_mean_using_pointer(double (*pf)(double, double), double number_1, double number_2); \ No newline at end of file diff --git a/python-c-api_solution/demolib.c b/python-c-api_solution/demolib.c index fcb2dba..f210145 100644 --- a/python-c-api_solution/demolib.c +++ b/python-c-api_solution/demolib.c @@ -27,7 +27,4 @@ int add_number_using_pointer(int (*pf)(int, int), int number_1, int number_2) { int result; result = pf(number_1, number_2); return result; -} - - - +} \ No newline at end of file -- GitLab