diff --git a/casting_pointer/main b/casting_pointer/main index 10c9409e09421519a3288a986fdb6b63949d7adb..189576e722ca7e9badc90be42295a87e88e9f158 100755 Binary files a/casting_pointer/main and b/casting_pointer/main differ diff --git a/casting_pointer/main.c b/casting_pointer/main.c index a93ed2609778144c8965549008eee9441fa860d5..e4f227fa897fb99e4da76b70cc9a8a3e9db9a1b6 100644 --- a/casting_pointer/main.c +++ b/casting_pointer/main.c @@ -1,14 +1,23 @@ #include <stdio.h> #include <stddef.h> - +#include <stdlib.h> +#include <stdint.h> typedef int (*fn_def)(void); + +typedef double(*fn_def2)(double, double); + int test1() { // function to call printf("Test\n"); } +double test2(double num1, double num2) +{ + printf("%f %f", num1, num2); +} + void convert_and_call(void *fnvptr_val) { // convert into pointer @@ -16,26 +25,44 @@ void convert_and_call(void *fnvptr_val) fnptr(); } +void convert_and_call2(void *fnvptr_val, double num1, double num2) +{ + // convert into pointer + fn_def2 fnptr = (fn_def2)fnvptr_val; + fnptr(num1, num2); +} int main() { void* fnvptr = (void*)&test1; + // // print adress + // printf("%p\n", &test1); - // print adress - printf("%p\n", &test1); + // printf("\n\nchar try\n"); + // // To char + // // cast into char array + // char* a=(char*)fnvptr; - // cast into char array - char* a=(char*)fnvptr; + // // print stuff + // printf("%s\n", a); + // printf("size: %ld\n",sizeof(a)); - // print stuff - printf("%s\n", a); - printf("size: %ld\n",sizeof(a)); + // // cast into new void thing + // void * fnvptr2 = (void*)a; + // printf("%p\n", fnvptr2); - // cast into new void thing - void * fnvptr2 = (void*)a; - printf("%p\n", fnvptr2); + // // // convert into pointer + // convert_and_call(fnvptr2); - // // convert into pointer - convert_and_call(fnvptr2); -} + void* fnvptr3_old = (void*)&test2; + printf("%p size: %ld\n", fnvptr3_old, sizeof(fnvptr3_old)); + char* fnvptr3_char=(char*)fnvptr3_old; + printf("%s has size %ld\n", fnvptr3_char, sizeof(fnvptr3_char)); + void * fnvptr3_new = (void*)fnvptr3_char; + printf("%p\n", fnvptr3_new); + + double numval_1 = 6.5; + double numval_2 = 5.0; + convert_and_call2(fnvptr3_new, numval_1, numval_2); +} \ No newline at end of file diff --git a/ctypes/compile.sh b/ctypes/compile.sh index 0c12cafce7ba9b593bd29f3198db768f01299ebf..e5b0c00db29a20edb9f98e80833899a3454dcf2a 100644 --- a/ctypes/compile.sh +++ b/ctypes/compile.sh @@ -1,3 +1,3 @@ # Compile a shared library gcc -shared -o libmean.so.1 -fPIC mean.c -gcc -o main -fPIC mean.c \ No newline at end of file +# gcc -o main -fPIC mean.c \ No newline at end of file diff --git a/ctypes/main.py b/ctypes/main.py index 67ad75ad878c39a2a4e784fd99abff14d9d4ae0c..763d02336585fa63e5a263ea451e87f41b4d2ac9 100644 --- a/ctypes/main.py +++ b/ctypes/main.py @@ -21,31 +21,32 @@ def buildLibrary(): if not s==0: print("return code:\n{}".format(s)) -# Building library -buildLibrary() +def loadLibraryFunction(): + # Building library + buildLibrary() -# Loading library -libmean = ctypes.CDLL("libmean.so.1") # loads the shared library + # Loading library + libmean = ctypes.CDLL("libmean.so.1") # loads the shared library -# # -# 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))) + # # + # 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 + # print some stuff + # print("pointer to mean function (via python code): {}".format(mem)) + # print("Hex memory adress: {}".format(hex(mem))) + # print(type(hex(mem))) + return hex(mem) +hex_mem = loadLibraryFunction() +print(hex_mem) # Other uses of this code diff --git a/ctypes/mean.c b/ctypes/mean.c index 31d46677fc7bb7b9d80ffef40640fa4b3bed9ec4..c8c1d178dccd4a52dad90f49137e32ef80f117b9 100644 --- a/ctypes/mean.c +++ b/ctypes/mean.c @@ -1,6 +1,7 @@ #include "mean.h" #include <stdio.h> #include <stdlib.h> +#include <math.h> double mean(double a, double b) { printf("calculating mean with %f and %f", a, b); @@ -16,9 +17,4 @@ double calc_mean_using_pointer(double (*pf)(double, double), double number_1, do 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 3fdc9b18b0abe3304e2110e95a7ab3d665366cbf..035946d9a0b19f0b67490d28bce7eabf94a4a9b9 100644 --- a/ctypes/mean.h +++ b/ctypes/mean.h @@ -1,5 +1,4 @@ - // Returns the mean of passed parameters 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 +double calc_mean_using_pointer(double (*pf)(double, double), double number_1, double number_2); diff --git a/ctypes_and_api/__pycache__/functions.cpython-36.pyc b/ctypes_and_api/__pycache__/functions.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5427d3f43ca347265356eea27b4a32d18b28153d Binary files /dev/null and b/ctypes_and_api/__pycache__/functions.cpython-36.pyc differ diff --git a/ctypes_and_api/compile_shared_lib.sh b/ctypes_and_api/compile_shared_lib.sh new file mode 100644 index 0000000000000000000000000000000000000000..e5b0c00db29a20edb9f98e80833899a3454dcf2a --- /dev/null +++ b/ctypes_and_api/compile_shared_lib.sh @@ -0,0 +1,3 @@ +# Compile a shared library +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_and_api/demolib.c b/ctypes_and_api/demolib.c new file mode 100644 index 0000000000000000000000000000000000000000..0d4af8cdadbdde4274d11f76ee9f54e44b10a7c9 --- /dev/null +++ b/ctypes_and_api/demolib.c @@ -0,0 +1,36 @@ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "demolib.h" + + +typedef double (*fn_def)(double, double); + +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; +} + +double calc_mean_using_pointer(long int str_1, double number_1, double number_2) +{ + printf("test for running function with mem addr %ld with arguments %f %f\n", str_1, number_1, number_2); + + // convert into pointer + fn_def fnptr = (fn_def)str_1; + + printf("size of function pointer %zu\n",sizeof(fnptr)); + printf("%p size: %zu\n", fnptr, sizeof(fnptr)); + + double result; + result = fnptr(number_1, number_2); + + return result; +} + +double test_func(char* str_1, double number_1, double number_2) { + // double result; + // result = pf(number_1, number_2); + printf("test for running function with mem addr %s with arguments %f %f\n", str_1, number_1, number_2); + return 6.5; +} \ No newline at end of file diff --git a/ctypes_and_api/demolib.h b/ctypes_and_api/demolib.h new file mode 100644 index 0000000000000000000000000000000000000000..805906094a1200689875a33eb4eadfdd024b7c07 --- /dev/null +++ b/ctypes_and_api/demolib.h @@ -0,0 +1,5 @@ +// Example header file + +// char construct_string(int number); +double calc_mean_using_pointer(long int str_1, double number_1, double number_2); +double test_func(char* str_1, double number_1, double number_2); \ No newline at end of file diff --git a/ctypes_and_api/demomodule.c b/ctypes_and_api/demomodule.c new file mode 100644 index 0000000000000000000000000000000000000000..90914d6be20aca37b7a7b1685c4af09d238a3783 --- /dev/null +++ b/ctypes_and_api/demomodule.c @@ -0,0 +1,67 @@ +// demomodule.c +#include <Python.h> +#include "demolib.h" + + +// https://stackoverflow.com/questions/51505391/how-to-parse-void-to-pyobject + +static PyObject *DemoLib_CalcMeanWithPointerTest(PyObject *self, PyObject *args) { + char *str_1; + double number_1; + double number_2; + if (!PyArg_ParseTuple(args, "sdd", &str_1, &number_1, &number_2)) { + return NULL; + } + + double result; + result = test_func(str_1, number_1, number_2); + return Py_BuildValue("d", result); +} + + +static PyObject *DemoLib_CalcMeanWithPointer(PyObject *self, PyObject *args) { + long int str_1; + double number_1; + double number_2; + if (!PyArg_ParseTuple(args, "ldd", &str_1, &number_1, &number_2)) { + return NULL; + } + + double result; + printf("%p contents %ld\n", &str_1, str_1); + result = calc_mean_using_pointer(str_1, number_1, number_2); + return Py_BuildValue("d", result); +} + +// module's function table +static PyMethodDef DemoLib_FunctionsTable[] = { + { + "calc_mean_with_pointer", // name exposed to Python + DemoLib_CalcMeanWithPointer, // C wrapper function + METH_VARARGS, // received variable args (but really just 1) + "Calculate the mean of two values via a pointer function" // documentation + }, + { + "calc_mean_with_pointer_test", // name exposed to Python + DemoLib_CalcMeanWithPointerTest, // C wrapper function + METH_VARARGS, // received variable args (but really just 1) + "Calculate the mean of two values via a pointer function" // documentation + }, + + { + NULL, NULL, 0, NULL + } +}; + +// modules definition +static struct PyModuleDef DemoLib_Module = { + PyModuleDef_HEAD_INIT, + "demo", // name of module exposed to Python + "Demo Python wrapper for custom C extension library.", // module documentation + -1, + DemoLib_FunctionsTable +}; + +PyMODINIT_FUNC PyInit_demo(void) { + return PyModule_Create(&DemoLib_Module); +} \ No newline at end of file diff --git a/ctypes_and_api/functions.py b/ctypes_and_api/functions.py new file mode 100644 index 0000000000000000000000000000000000000000..ccb9b38c54c1fab241389ad42375b4acd29b3040 --- /dev/null +++ b/ctypes_and_api/functions.py @@ -0,0 +1,43 @@ +import ctypes +import os +import subprocess + +def buildLibrary(): + # store the return code of the c program(return 0) + # and display the output + s = subprocess.check_call("bash compile_shared_lib.sh", shell=True) + if not s==0: + print("return code:\n{}".format(s)) + +def loadLibraryFunction(): + # OLD + + # Building library + buildLibrary() + + # Loading library + libmean = ctypes.CDLL("libmean.so.1") # loads the shared library + + # # + # 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 + + # print some stuff + # 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))) + + return mem \ No newline at end of file diff --git a/ctypes_and_api/libmean.so.1 b/ctypes_and_api/libmean.so.1 new file mode 100755 index 0000000000000000000000000000000000000000..df6280d836c719bec47c764d75c8a0222edbf955 Binary files /dev/null and b/ctypes_and_api/libmean.so.1 differ diff --git a/ctypes_and_api/main.py b/ctypes_and_api/main.py new file mode 100644 index 0000000000000000000000000000000000000000..b3af562518c0d270a3de9f338d017a3227904e0d --- /dev/null +++ b/ctypes_and_api/main.py @@ -0,0 +1,22 @@ +import ctypes +import os +import subprocess + +from functions import loadLibraryFunction, buildLibrary + +import demo + + + +buildLibrary() + +# Loading library +libmean = ctypes.CDLL("libmean.so.1") # loads the shared library + +# Get memory adress of function. mimicking a pointer +mem = ctypes.cast(libmean.mean, ctypes.c_void_p).value +print("mem adress of mean function {}, type: {}".format(mem, type(mem))) + + +dong = demo.calc_mean_with_pointer(mem, 1.0, 2.0) +print(dong) \ No newline at end of file diff --git a/ctypes_and_api/mean.c b/ctypes_and_api/mean.c new file mode 100644 index 0000000000000000000000000000000000000000..c8c1d178dccd4a52dad90f49137e32ef80f117b9 --- /dev/null +++ b/ctypes_and_api/mean.c @@ -0,0 +1,20 @@ +#include "mean.h" +#include <stdio.h> +#include <stdlib.h> +#include <math.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; +} \ No newline at end of file diff --git a/ctypes_and_api/mean.h b/ctypes_and_api/mean.h new file mode 100644 index 0000000000000000000000000000000000000000..035946d9a0b19f0b67490d28bce7eabf94a4a9b9 --- /dev/null +++ b/ctypes_and_api/mean.h @@ -0,0 +1,4 @@ +// Returns the mean of passed parameters +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); diff --git a/ctypes_and_api/readme.org b/ctypes_and_api/readme.org new file mode 100644 index 0000000000000000000000000000000000000000..e3a32fc5ca6738f068799b3a91f050ac72bdd225 --- /dev/null +++ b/ctypes_and_api/readme.org @@ -0,0 +1,30 @@ +* Idea: +- In the main function we compile the functions mean.c and mean.h to a shared library, calling it libmean.so.1 +- this library gets loaded into memory with ctypes.CDLL(<name lib>) +- the memory adress, and two floats get given to a c function that is bound with python through the python-c-api: + - these are defined in demolib.c + - these are connected with python using demomodule.c + +- within that c function, the memory adress is made into the pointer to the function that is contained in the loaded shared library. +- This pointer is then called, with the two numbers and returns an output + + + +* usage: +in this directory: pip install . --upgrade + +then run python main.py + + +* Some leads: + +# https://solarianprogrammer.com/2019/07/18/python-using-c-cpp-libraries-ctypes/ +# https://gist.github.com/elyezer/7099291 + +# https://www.geeksforgeeks.org/turning-a-function-pointer-to-callable/ +# 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 +# https://blog.regehr.org/archives/1621 +# https://www.oreilly.com/library/view/understanding-and-using/9781449344535/ch01.html \ No newline at end of file diff --git a/ctypes_and_api/setup.py b/ctypes_and_api/setup.py new file mode 100644 index 0000000000000000000000000000000000000000..0354312c193a3abc6b4495d4ecafbf759744cbb6 --- /dev/null +++ b/ctypes_and_api/setup.py @@ -0,0 +1,11 @@ +from setuptools import Extension, setup + +module = Extension("demo", + sources=[ + 'demolib.c', + 'demomodule.c' + ]) +setup(name='demo', + version='1.0', + description='Python wrapper for custom C extension', + ext_modules=[module]) \ No newline at end of file diff --git a/python-c-api_solution/demolib.o b/python-c-api_solution/demolib.o deleted file mode 100644 index ffc6c06f550025b0a750c2196115c828d48087e8..0000000000000000000000000000000000000000 Binary files a/python-c-api_solution/demolib.o and /dev/null differ diff --git a/python-c-api_solution/main.c b/python-c-api_solution/main.c index 27d24aa9d22c89ba889d0551a5987a91093fcb2a..4d412f8b62707b870dab005dccb3a13b94e5e674 100644 --- a/python-c-api_solution/main.c +++ b/python-c-api_solution/main.c @@ -2,11 +2,6 @@ #include <stdlib.h> #include "demolib.h" - - - - - int main(void) { // Testing stuff for add_number function int getal_1=2; @@ -53,15 +48,6 @@ int main(void) { function_via_pointer_res_2 = add_number_using_pointer(pf3, 10, 20); printf("result of calling a function with a function pointer to multiply_number: %d\n", function_via_pointer_res_2); - // - - - - - - - - return(0); -} \ No newline at end of file +} diff --git a/python-c-api_solution/main.o b/python-c-api_solution/main.o deleted file mode 100644 index da6dae0c35829ddfa9513192e590a17c9e87cb85..0000000000000000000000000000000000000000 Binary files a/python-c-api_solution/main.o and /dev/null differ