C++¤
Load the example 64-bit C++ library in 64-bit Python. To load the 32-bit library in 32-bit Python use "cpp_lib32"
as the filename.
Tip
If the file extension is not specified, a default extension, .dll
(Windows), .so
(Linux) or .dylib
(macOS) is used.
Example¤
Load the example C++ library
>>> from msl.loadlib import LoadLibrary
>>> from msl.examples.loadlib import EXAMPLES_DIR
>>> cpp = LoadLibrary(EXAMPLES_DIR / "cpp_lib64")
By default, ctypes treats all input argument types and the return type of a library function to be a c_int. Therefore, the argtypes and the restype should be defined for each function in the library. A few examples for the C++ library are shown below
>>> from ctypes import c_char_p, c_float, c_int32
>>> cpp.lib.subtract.argtypes = [c_float, c_float]
>>> cpp.lib.subtract.restype = c_float
>>> cpp.lib.reverse_string_v1.argtypes = [c_char_p, c_int32, c_char_p]
>>> cpp.lib.reverse_string_v1.restype = None
Call the add
function to calculate the sum of two integers
>>> cpp.lib.add(1, 2)
3
Call the subtract
function to calculate the difference between two floats
>>> cpp.lib.subtract(7.1, 2.1)
5.0
Call the reverse_string_v1
function to reverse the characters in a byte string. Python manages the memory of the reversed sting by creating a string buffer of the necessary length
>>> from ctypes import create_string_buffer
>>> original = b"olleh"
>>> reverse = create_string_buffer(len(original))
>>> cpp.lib.reverse_string_v1(original, len(original), reverse)
>>> reverse.raw.decode()
'hello'
C++ Source Code¤
cpp_lib
// cpp_lib.cpp
// Examples that show how to pass various data types between Python and a C++ library.
//
// Compiled using:
// g++ cpp_lib.cpp -fPIC -shared -Bstatic -Wall -o cpp_lib64.so
//
#include <math.h>
#include "cpp_lib.h"
int add(int a, int b) {
return a + b;
}
float subtract(float a, float b) {
return a - b;
}
double add_or_subtract(double a, double b, bool do_addition) {
if (do_addition) {
return a + b;
} else {
return a - b;
}
}
void scalar_multiply(double a, double* xin, int n, double* xout) {
for (int i = 0; i < n; i++) {
xout[i] = a * xin[i];
}
}
void reverse_string_v1(const char* original, int n, char* reversed) {
for (int i = 0; i < n; i++) {
reversed[i] = original[n-i-1];
}
}
char* reverse_string_v2(char* original, int n) {
char* reversed = new char[n];
for (int i = 0; i < n; i++) {
reversed[i] = original[n - i - 1];
}
return reversed;
}
// this function is not exported to the shared library
double distance(Point p1, Point p2) {
double d = sqrt(pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2));
return d;
}
double distance_4_points(FourPoints p) {
double d = distance(p.points[0], p.points[3]);
for (int i = 1; i < 4; i++) {
d += distance(p.points[i], p.points[i-1]);
}
return d;
}
double distance_n_points(NPoints p) {
if (p.n < 2) {
return 0.0;
}
double d = distance(p.points[0], p.points[p.n-1]);
for (int i = 1; i < p.n; i++) {
d += distance(p.points[i], p.points[i-1]);
}
return d;
}
// cpp_lib.h
// Contains the declaration of exported functions.
//
#if defined(_MSC_VER)
// Microsoft
#define EXPORT __declspec(dllexport)
#elif defined(__GNUC__)
// G++
#define EXPORT __attribute__((visibility("default")))
#else
# error "Unknown EXPORT semantics"
#endif
struct Point {
double x;
double y;
};
struct FourPoints {
Point points[4];
};
struct NPoints {
int n;
Point *points;
};
extern "C" {
// a + b
EXPORT int add(int a, int b);
// a - b
EXPORT float subtract(float a, float b);
// IF do_addition IS TRUE THEN a + b ELSE a - b
EXPORT double add_or_subtract(double a, double b, bool do_addition);
// multiply each element in 'x' by 'a'
EXPORT void scalar_multiply(double a, double* xin, int n, double* xout);
// reverse a string
EXPORT void reverse_string_v1(const char* original, int n, char* reversed);
// reverse a string and return it
EXPORT char* reverse_string_v2(char* original, int n);
// calculate the total distance connecting 4 Points
EXPORT double distance_4_points(FourPoints p);
// calculate the total distance connecting N Points
EXPORT double distance_n_points(NPoints p);
}