add files

This commit is contained in:
wangziao 2025-07-06 11:18:03 -07:00
parent c0e4f9afd3
commit c49ed3b13e
12 changed files with 137 additions and 2 deletions

View File

@ -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
View 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
View 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
View 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

Binary file not shown.

BIN
calling-c/hello.so Normal file

Binary file not shown.

8
calling-cpp/Makefile Normal file
View 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

Binary file not shown.

BIN
calling-cpp/callee.so Normal file

Binary file not shown.

10
calling-cpp/caller.py Normal file
View 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
View 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
View File

@ -0,0 +1,4 @@
extern "C"{
bool isprime(long long);
long long sumprimes(long long);
}