add files
This commit is contained in:
parent
c0e4f9afd3
commit
c49ed3b13e
11
README.md
11
README.md
@ -1,3 +1,10 @@
|
||||
# python-calling-c-cpp
|
||||
To list every symbol in a dll, use "nm".
|
||||
|
||||
Example of calling C and C++ functions in Python
|
||||
"nm -g hello.so" output "T square", where hello.so is created from a **C** source file containing function square.
|
||||
"nm -g callee.so" output "T \_Z7isprimex", "_Z9sumprimesx", where callee.so is created from a **C++** file containing function isprime and sumprimes.
|
||||
|
||||
Why does the names differ? C++ compilers use "name mangling" to support overloading, etc, resulting in names that differ from names in the source file. This is not done in C compilers (since C does not support overloading as well).
|
||||
|
||||
To prevent name mangling, use `extern "C"` directive in the function declaration.
|
||||
The extern keyword may be applied to a global variable, function, or template declaration. It specifies that the symbol has external linkage.
|
||||
`extern "C"` specifies that the function is defined elsewhere and uses the C-language calling convention, which includes do not mangle names.
|
8
calling-c/Makefile
Normal file
8
calling-c/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
hello.so: hello.o
|
||||
gcc -shared -o hello.so hello.o
|
||||
|
||||
hello.o: hello.c
|
||||
gcc -std=c99 -c -o hello.o hello.c
|
||||
|
||||
clean:
|
||||
rm hello.o hello.so
|
43
calling-c/caller.py
Normal file
43
calling-c/caller.py
Normal file
@ -0,0 +1,43 @@
|
||||
import ctypes
|
||||
hello_lib = ctypes.CDLL('./hello.so') #/windows
|
||||
|
||||
# 1. Square (int -> int)
|
||||
hello_lib.square.argtypes = [ctypes.c_int]
|
||||
hello_lib.square.restype = ctypes.c_int
|
||||
|
||||
x = 4
|
||||
result = hello_lib.square(x)
|
||||
print(f'the square of {x} is {result}')
|
||||
|
||||
hello_lib.sum_elements.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.c_int]
|
||||
hello_lib.sum_elements.restype = ctypes.c_int
|
||||
|
||||
# 2. Sum (int*, int -> int)
|
||||
N = 4
|
||||
p = [3, 1, 2, 4]
|
||||
# Converts Python list to C array. (*p) is equivalent to (3, 1, 2, 4)
|
||||
c_array = (ctypes.c_int * len(p))(*p)
|
||||
# Get the address of the array
|
||||
p_pointer = ctypes.cast(c_array, ctypes.POINTER(ctypes.c_int))
|
||||
|
||||
result = hello_lib.sum_elements(p_pointer, N) # pass in p_pointer or c_array both works
|
||||
print(f"the sum of the array is {result}")
|
||||
|
||||
import numpy as np
|
||||
from numpy.ctypeslib import ndpointer
|
||||
|
||||
# 3. Sort (in place float*)
|
||||
hello_lib.bubble_sort.argtypes = [ndpointer(dtype=np.float32, flags='C_CONTIGUOUS'), ctypes.c_int]
|
||||
hello_lib.bubble_sort.restype = None
|
||||
arr = np.array([3.0, 2.3, 4.2, 1.9, 3.2, 1.7], dtype=np.float32)
|
||||
hello_lib.bubble_sort(arr, len(arr))
|
||||
print(arr)
|
||||
|
||||
# 4. Create (int, float -> float*)
|
||||
a = 0.523
|
||||
N = 6
|
||||
hello_lib.generate_sine_values.argtypes = [ctypes.c_float, ctypes.c_int]
|
||||
hello_lib.generate_sine_values.restype = ndpointer(dtype=np.float32, shape=(N,))
|
||||
result_arr = hello_lib.generate_sine_values(a, N)
|
||||
print(type(result_arr))
|
||||
print(result_arr)
|
34
calling-c/hello.c
Normal file
34
calling-c/hello.c
Normal file
@ -0,0 +1,34 @@
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int square(int x) {
|
||||
return x*x;
|
||||
}
|
||||
|
||||
int sum_elements(int *p, int N) {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < N; i++) {
|
||||
sum += p[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
void bubble_sort(float *p, int N){
|
||||
for (int i=0;i<N-1;i++){
|
||||
for (int j=0;j<N-i-1;j++){
|
||||
if (p[j]>p[j+1]){
|
||||
float temp = p[j];
|
||||
p[j] = p[j+1];
|
||||
p[j+1] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float *generate_sine_values(float a, int N) {
|
||||
float *result = malloc(N * sizeof(float));
|
||||
for (int k = 0; k < N; ++k) {
|
||||
result[k] = sin(k * a);
|
||||
}
|
||||
return result;
|
||||
}
|
BIN
calling-c/hello.o
Normal file
BIN
calling-c/hello.o
Normal file
Binary file not shown.
BIN
calling-c/hello.so
Normal file
BIN
calling-c/hello.so
Normal file
Binary file not shown.
8
calling-cpp/Makefile
Normal file
8
calling-cpp/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
callee.o: workload.cpp workload.h
|
||||
g++ -c workload.cpp -o callee.o
|
||||
|
||||
callee.so: callee.o
|
||||
g++ -shared -o callee.so callee.o
|
||||
|
||||
clean:
|
||||
rm callee.o callee.so
|
BIN
calling-cpp/callee.o
Normal file
BIN
calling-cpp/callee.o
Normal file
Binary file not shown.
BIN
calling-cpp/callee.so
Normal file
BIN
calling-cpp/callee.so
Normal file
Binary file not shown.
10
calling-cpp/caller.py
Normal file
10
calling-cpp/caller.py
Normal file
@ -0,0 +1,10 @@
|
||||
import ctypes
|
||||
from ctypes import c_int64
|
||||
|
||||
my_lib = ctypes.CDLL('./callee.so')
|
||||
|
||||
my_lib.sumprimes.argtypes = [ctypes.c_int64]
|
||||
my_lib.sumprimes.restype = ctypes.c_int64
|
||||
x = input("input x:")
|
||||
result = my_lib.sumprimes(int(x))
|
||||
print(result)
|
21
calling-cpp/workload.cpp
Normal file
21
calling-cpp/workload.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "workload.h"
|
||||
|
||||
bool isprime(long long x){
|
||||
if (x < 2) return false;
|
||||
for (long long i = 2; i*i <= x ; i++) {
|
||||
if (x % i == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
long long sumprimes(long long bound){
|
||||
long long total = 0;
|
||||
for (long long i = 1; i <= bound; i++){
|
||||
if (isprime(i)) {
|
||||
total += i;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
4
calling-cpp/workload.h
Normal file
4
calling-cpp/workload.h
Normal file
@ -0,0 +1,4 @@
|
||||
extern "C"{
|
||||
bool isprime(long long);
|
||||
long long sumprimes(long long);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user