msl-loadlib 1.0.0__py3-none-win32.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- msl/examples/loadlib/Trig.class +0 -0
- msl/examples/loadlib/__init__.py +38 -0
- msl/examples/loadlib/cpp32.py +368 -0
- msl/examples/loadlib/cpp64.py +157 -0
- msl/examples/loadlib/cpp_lib32.dll +0 -0
- msl/examples/loadlib/cpp_lib64.dll +0 -0
- msl/examples/loadlib/dotnet32.py +346 -0
- msl/examples/loadlib/dotnet64.py +186 -0
- msl/examples/loadlib/dotnet_lib32.dll +0 -0
- msl/examples/loadlib/dotnet_lib64.dll +0 -0
- msl/examples/loadlib/echo32.py +44 -0
- msl/examples/loadlib/echo64.py +36 -0
- msl/examples/loadlib/fortran32.py +551 -0
- msl/examples/loadlib/fortran64.py +238 -0
- msl/examples/loadlib/fortran_lib32.dll +0 -0
- msl/examples/loadlib/fortran_lib64.dll +0 -0
- msl/examples/loadlib/java_lib.jar +0 -0
- msl/examples/loadlib/kernel32.py +76 -0
- msl/examples/loadlib/kernel64.py +46 -0
- msl/examples/loadlib/labview32.py +56 -0
- msl/examples/loadlib/labview64.py +51 -0
- msl/examples/loadlib/labview_lib32.dll +0 -0
- msl/examples/loadlib/labview_lib64.dll +0 -0
- msl/examples/loadlib/py.typed +1 -0
- msl/loadlib/__about__.py +15 -0
- msl/loadlib/__init__.py +27 -0
- msl/loadlib/_constants.py +42 -0
- msl/loadlib/_types.py +26 -0
- msl/loadlib/_version.py +21 -0
- msl/loadlib/activex.py +1221 -0
- msl/loadlib/client64.py +647 -0
- msl/loadlib/exceptions.py +66 -0
- msl/loadlib/freeze_server32.py +437 -0
- msl/loadlib/load_library.py +478 -0
- msl/loadlib/py.typed +1 -0
- msl/loadlib/py4j-wrapper.jar +0 -0
- msl/loadlib/server32-windows.exe +0 -0
- msl/loadlib/server32-windows.exe.config +22 -0
- msl/loadlib/server32.py +311 -0
- msl/loadlib/start_server32.py +309 -0
- msl/loadlib/utils.py +415 -0
- msl_loadlib-1.0.0.dist-info/METADATA +216 -0
- msl_loadlib-1.0.0.dist-info/RECORD +46 -0
- msl_loadlib-1.0.0.dist-info/WHEEL +4 -0
- msl_loadlib-1.0.0.dist-info/entry_points.txt +2 -0
- msl_loadlib-1.0.0.dist-info/licenses/LICENSE.txt +21 -0
|
Binary file
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Examples showing how to load a 32-bit library in 64-bit Python."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from .cpp32 import Cpp32, FourPoints, NPoints, Point
|
|
8
|
+
from .cpp64 import Cpp64
|
|
9
|
+
from .dotnet32 import DotNet32
|
|
10
|
+
from .dotnet64 import DotNet64
|
|
11
|
+
from .echo32 import Echo32
|
|
12
|
+
from .echo64 import Echo64
|
|
13
|
+
from .fortran32 import Fortran32
|
|
14
|
+
from .fortran64 import Fortran64
|
|
15
|
+
from .kernel32 import Kernel32
|
|
16
|
+
from .kernel64 import Kernel64
|
|
17
|
+
from .labview32 import Labview32
|
|
18
|
+
from .labview64 import Labview64
|
|
19
|
+
|
|
20
|
+
EXAMPLES_DIR: Path = Path(__file__).parent
|
|
21
|
+
|
|
22
|
+
__all__: list[str] = [
|
|
23
|
+
"Cpp32",
|
|
24
|
+
"Cpp64",
|
|
25
|
+
"DotNet32",
|
|
26
|
+
"DotNet64",
|
|
27
|
+
"Echo32",
|
|
28
|
+
"Echo64",
|
|
29
|
+
"Fortran32",
|
|
30
|
+
"Fortran64",
|
|
31
|
+
"FourPoints",
|
|
32
|
+
"Kernel32",
|
|
33
|
+
"Kernel64",
|
|
34
|
+
"Labview32",
|
|
35
|
+
"Labview64",
|
|
36
|
+
"NPoints",
|
|
37
|
+
"Point",
|
|
38
|
+
]
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
"""Wrapper around a 32-bit C++ library.
|
|
2
|
+
|
|
3
|
+
Example of a server that loads a 32-bit library, [cpp_lib][cpp-lib],
|
|
4
|
+
in a 32-bit Python interpreter to host the library. The corresponding [Cpp64][] class
|
|
5
|
+
is created in a 64-bit Python interpreter and the [Cpp64][] class sends requests
|
|
6
|
+
to the [Cpp32][] class which calls the 32-bit library to execute the request and
|
|
7
|
+
then returns the response from the library.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import ctypes
|
|
13
|
+
import math
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import TYPE_CHECKING
|
|
16
|
+
|
|
17
|
+
from msl.loadlib import Server32
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from collections.abc import Sequence
|
|
21
|
+
from ctypes import Array
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Cpp32(Server32):
|
|
25
|
+
"""Wrapper around a 32-bit C++ library."""
|
|
26
|
+
|
|
27
|
+
def __init__(self, host: str, port: int) -> None:
|
|
28
|
+
"""Wrapper around a 32-bit C++ library.
|
|
29
|
+
|
|
30
|
+
This class demonstrates how to send/receive various data types to/from a
|
|
31
|
+
32-bit C++ library via [ctypes][]{:target="_blank"}.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
host: The IP address (or hostname) to use for the server.
|
|
35
|
+
port: The port to open for the server.
|
|
36
|
+
"""
|
|
37
|
+
# By not specifying the extension of the library file the server will open
|
|
38
|
+
# the appropriate file based on the operating system.
|
|
39
|
+
path = Path(__file__).parent / "cpp_lib32"
|
|
40
|
+
super().__init__(path, "cdll", host, port)
|
|
41
|
+
|
|
42
|
+
def add(self, a: int, b: int) -> int:
|
|
43
|
+
"""Add two integers.
|
|
44
|
+
|
|
45
|
+
The corresponding C++ code is
|
|
46
|
+
|
|
47
|
+
```cpp
|
|
48
|
+
int add(int a, int b) {
|
|
49
|
+
return a + b;
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
See the corresponding [Cpp64.add][msl.examples.loadlib.Cpp64.add] method.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
a: First integer.
|
|
57
|
+
b: Second integer.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
The sum, `a + b`.
|
|
61
|
+
"""
|
|
62
|
+
# restype and argtypes should be defined elsewhere, shown here for illustrative purposes
|
|
63
|
+
self.lib.add.restype = ctypes.c_int32
|
|
64
|
+
self.lib.add.argtypes = [ctypes.c_int32, ctypes.c_int32]
|
|
65
|
+
result: int = self.lib.add(a, b)
|
|
66
|
+
return result
|
|
67
|
+
|
|
68
|
+
def subtract(self, a: float, b: float) -> float:
|
|
69
|
+
"""Subtract two floating-point numbers *('float' refers to the C++ data type)*.
|
|
70
|
+
|
|
71
|
+
The corresponding C++ code is
|
|
72
|
+
|
|
73
|
+
```cpp
|
|
74
|
+
float subtract(float a, float b) {
|
|
75
|
+
return a - b;
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
See the corresponding [Cpp64.subtract][msl.examples.loadlib.Cpp64.subtract] method.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
a: First floating-point number.
|
|
83
|
+
b: Second floating-point number.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
The difference, `a - b`.
|
|
87
|
+
"""
|
|
88
|
+
# restype and argtypes should be defined elsewhere, shown here for illustrative purposes
|
|
89
|
+
self.lib.subtract.restype = ctypes.c_float
|
|
90
|
+
self.lib.subtract.argtypes = [ctypes.c_float, ctypes.c_float]
|
|
91
|
+
result: float = self.lib.subtract(a, b)
|
|
92
|
+
return result
|
|
93
|
+
|
|
94
|
+
def add_or_subtract(self, a: float, b: float, *, do_addition: bool) -> float:
|
|
95
|
+
"""Add or subtract two double-precision numbers *('double' refers to the C++ data type)*.
|
|
96
|
+
|
|
97
|
+
The corresponding C++ code is
|
|
98
|
+
|
|
99
|
+
```cpp
|
|
100
|
+
double add_or_subtract(double a, double b, bool do_addition) {
|
|
101
|
+
if (do_addition) {
|
|
102
|
+
return a + b;
|
|
103
|
+
} else {
|
|
104
|
+
return a - b;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
See the corresponding [Cpp64.add_or_subtract][msl.examples.loadlib.Cpp64.add_or_subtract] method.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
a: First double-precision number.
|
|
113
|
+
b: Second double-precision number.
|
|
114
|
+
do_addition: Whether to add or subtract the numbers.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
`a + b` if `do_addition` is `True` else `a - b`.
|
|
118
|
+
"""
|
|
119
|
+
# restype and argtypes should be defined elsewhere, shown here for illustrative purposes
|
|
120
|
+
self.lib.add_or_subtract.restype = ctypes.c_double
|
|
121
|
+
self.lib.add_or_subtract.argtypes = [ctypes.c_double, ctypes.c_double, ctypes.c_bool]
|
|
122
|
+
result: float = self.lib.add_or_subtract(a, b, do_addition)
|
|
123
|
+
return result
|
|
124
|
+
|
|
125
|
+
def scalar_multiply(self, a: float, xin: Sequence[float]) -> list[float]:
|
|
126
|
+
"""Multiply each element in an array by a number.
|
|
127
|
+
|
|
128
|
+
The corresponding C++ code is
|
|
129
|
+
|
|
130
|
+
```cpp
|
|
131
|
+
void scalar_multiply(double a, double* xin, int n, double* xout) {
|
|
132
|
+
for (int i = 0; i < n; i++) {
|
|
133
|
+
xout[i] = a * xin[i];
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
See the corresponding [Cpp64.scalar_multiply][msl.examples.loadlib.Cpp64.scalar_multiply] method.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
a: Scalar value.
|
|
142
|
+
xin: Array to modify.
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
A new array with each element in `xin` multiplied by `a`.
|
|
146
|
+
"""
|
|
147
|
+
# restype and argtypes should be defined elsewhere, shown here for illustrative purposes
|
|
148
|
+
self.lib.scalar_multiply.restype = None
|
|
149
|
+
self.lib.scalar_multiply.argtypes = [
|
|
150
|
+
ctypes.c_double,
|
|
151
|
+
ctypes.POINTER(ctypes.c_double),
|
|
152
|
+
ctypes.c_int32,
|
|
153
|
+
ctypes.POINTER(ctypes.c_double),
|
|
154
|
+
]
|
|
155
|
+
|
|
156
|
+
n = len(xin)
|
|
157
|
+
c_xin = (ctypes.c_double * n)(*xin) # convert input array to ctypes
|
|
158
|
+
c_xout = (ctypes.c_double * n)() # allocate memory for output array
|
|
159
|
+
self.lib.scalar_multiply(a, c_xin, n, c_xout)
|
|
160
|
+
return list(c_xout)
|
|
161
|
+
|
|
162
|
+
def reverse_string_v1(self, original: str) -> str:
|
|
163
|
+
"""Reverse a string (version 1).
|
|
164
|
+
|
|
165
|
+
In this method Python allocates the memory for the reversed string and
|
|
166
|
+
passes the string to C++.
|
|
167
|
+
|
|
168
|
+
The corresponding C++ code is
|
|
169
|
+
|
|
170
|
+
```cpp
|
|
171
|
+
void reverse_string_v1(const char* original, int n, char* reversed) {
|
|
172
|
+
for (int i = 0; i < n; i++) {
|
|
173
|
+
reversed[i] = original[n-i-1];
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
See the corresponding [Cpp64.reverse_string_v1][msl.examples.loadlib.Cpp64.reverse_string_v1] method.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
original: The original string.
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
The string reversed.
|
|
185
|
+
"""
|
|
186
|
+
# restype and argtypes should be defined elsewhere, shown here for illustrative purposes
|
|
187
|
+
self.lib.reverse_string_v1.restype = None
|
|
188
|
+
self.lib.reverse_string_v1.argtypes = [ctypes.c_char_p, ctypes.c_int32, ctypes.c_char_p]
|
|
189
|
+
|
|
190
|
+
n = len(original)
|
|
191
|
+
rev = ctypes.create_string_buffer(n)
|
|
192
|
+
self.lib.reverse_string_v1(original.encode(), n, rev)
|
|
193
|
+
return rev.raw.decode()
|
|
194
|
+
|
|
195
|
+
def reverse_string_v2(self, original: str) -> str:
|
|
196
|
+
"""Reverse a string (version 2).
|
|
197
|
+
|
|
198
|
+
In this method C++ allocates the memory for the reversed string and passes
|
|
199
|
+
the string to Python.
|
|
200
|
+
|
|
201
|
+
The corresponding C++ code is
|
|
202
|
+
|
|
203
|
+
```cpp
|
|
204
|
+
char* reverse_string_v2(char* original, int n) {
|
|
205
|
+
char* reversed = new char[n];
|
|
206
|
+
for (int i = 0; i < n; i++) {
|
|
207
|
+
reversed[i] = original[n - i - 1];
|
|
208
|
+
}
|
|
209
|
+
return reversed;
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
See the corresponding [Cpp64.reverse_string_v2][msl.examples.loadlib.Cpp64.reverse_string_v2] method.
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
original: The original string.
|
|
217
|
+
|
|
218
|
+
Returns:
|
|
219
|
+
The string reversed.
|
|
220
|
+
"""
|
|
221
|
+
# restype and argtypes should be defined elsewhere, shown here for illustrative purposes
|
|
222
|
+
self.lib.reverse_string_v2.restype = ctypes.c_char_p
|
|
223
|
+
self.lib.reverse_string_v2.argtypes = [ctypes.c_char_p, ctypes.c_int32]
|
|
224
|
+
|
|
225
|
+
n = len(original)
|
|
226
|
+
rev = self.lib.reverse_string_v2(original.encode(), n)
|
|
227
|
+
return ctypes.string_at(rev, n).decode()
|
|
228
|
+
|
|
229
|
+
def distance_4_points(self, four_points: FourPoints) -> float:
|
|
230
|
+
"""Calculates the total distance connecting 4 [Point][msl.examples.loadlib.cpp32.Point]s.
|
|
231
|
+
|
|
232
|
+
The corresponding C++ code is
|
|
233
|
+
|
|
234
|
+
```cpp
|
|
235
|
+
double distance_4_points(FourPoints p) {
|
|
236
|
+
double d = distance(p.points[0], p.points[3]);
|
|
237
|
+
for (int i = 1; i < 4; i++) {
|
|
238
|
+
d += distance(p.points[i], p.points[i-1]);
|
|
239
|
+
}
|
|
240
|
+
return d;
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
See the corresponding [Cpp64.distance_4_points][msl.examples.loadlib.Cpp64.distance_4_points] method.
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
four_points: The points to use to calculate the total distance.
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
The total distance connecting the 4 points.
|
|
251
|
+
"""
|
|
252
|
+
# restype should be defined elsewhere, shown here for illustrative purposes
|
|
253
|
+
self.lib.distance_4_points.restype = ctypes.c_double
|
|
254
|
+
result: float = self.lib.distance_4_points(four_points)
|
|
255
|
+
return result
|
|
256
|
+
|
|
257
|
+
def circumference(self, radius: float, n: int) -> float:
|
|
258
|
+
"""Estimates the circumference of a circle.
|
|
259
|
+
|
|
260
|
+
This method calls the `distance_n_points` function in [cpp_lib][cpp-lib].
|
|
261
|
+
|
|
262
|
+
The corresponding C++ code uses the [NPoints][msl.examples.loadlib.cpp32.NPoints]
|
|
263
|
+
struct as the input parameter to sum the distance between adjacent points on the circle.
|
|
264
|
+
|
|
265
|
+
```cpp
|
|
266
|
+
double distance_n_points(NPoints p) {
|
|
267
|
+
if (p.n < 2) {
|
|
268
|
+
return 0.0;
|
|
269
|
+
}
|
|
270
|
+
double d = distance(p.points[0], p.points[p.n-1]);
|
|
271
|
+
for (int i = 1; i < p.n; i++) {
|
|
272
|
+
d += distance(p.points[i], p.points[i-1]);
|
|
273
|
+
}
|
|
274
|
+
return d;
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
See the corresponding [Cpp64.circumference][msl.examples.loadlib.Cpp64.circumference] method.
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
radius: The radius of the circle.
|
|
282
|
+
n: The number of points to use to estimate the circumference.
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
The estimated circumference of the circle.
|
|
286
|
+
"""
|
|
287
|
+
# restype and argtypes should be defined elsewhere, shown here for illustrative purposes
|
|
288
|
+
self.lib.distance_n_points.restype = ctypes.c_double
|
|
289
|
+
self.lib.distance_n_points.argtypes = [NPoints]
|
|
290
|
+
|
|
291
|
+
theta = 0.0
|
|
292
|
+
delta = (2.0 * math.pi) / float(n) if n != 0 else 0
|
|
293
|
+
|
|
294
|
+
pts = NPoints()
|
|
295
|
+
pts.n = n
|
|
296
|
+
pts.points = (Point * n)()
|
|
297
|
+
for i in range(n):
|
|
298
|
+
pts.points[i] = Point(radius * math.cos(theta), radius * math.sin(theta))
|
|
299
|
+
theta += delta
|
|
300
|
+
result: float = self.lib.distance_n_points(pts)
|
|
301
|
+
return result
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
class Point(ctypes.Structure):
|
|
305
|
+
"""C++ struct that is a fixed size in memory.
|
|
306
|
+
|
|
307
|
+
This object can be [pickle][]{:target="_blank"}d.
|
|
308
|
+
|
|
309
|
+
```cpp
|
|
310
|
+
struct Point {
|
|
311
|
+
double x;
|
|
312
|
+
double y;
|
|
313
|
+
};
|
|
314
|
+
```
|
|
315
|
+
"""
|
|
316
|
+
|
|
317
|
+
_fields_ = ( # pyright: ignore[reportUnannotatedClassAttribute]
|
|
318
|
+
("x", ctypes.c_double),
|
|
319
|
+
("y", ctypes.c_double),
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
class FourPoints(ctypes.Structure):
|
|
324
|
+
"""C++ struct that is a fixed size in memory."""
|
|
325
|
+
|
|
326
|
+
_fields_ = ( # pyright: ignore[reportUnannotatedClassAttribute]
|
|
327
|
+
("points", (Point * 4)),
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
def __init__(self, point1: Point, point2: Point, point3: Point, point4: Point) -> None:
|
|
331
|
+
"""C++ struct that is a fixed size in memory.
|
|
332
|
+
|
|
333
|
+
This object can be [pickle][]{:target="_blank"}d.
|
|
334
|
+
|
|
335
|
+
```cpp
|
|
336
|
+
struct FourPoints {
|
|
337
|
+
Point points[4];
|
|
338
|
+
};
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
Args:
|
|
342
|
+
point1: The first point.
|
|
343
|
+
point2: The second point.
|
|
344
|
+
point3: The third point.
|
|
345
|
+
point4: The fourth point.
|
|
346
|
+
"""
|
|
347
|
+
super().__init__()
|
|
348
|
+
self.points: Array[Point] = (Point * 4)(point1, point2, point3, point4)
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
class NPoints(ctypes.Structure):
|
|
352
|
+
"""C++ struct that is **not** a fixed size in memory.
|
|
353
|
+
|
|
354
|
+
This object cannot be [pickle][]{:target="_blank"}d because it contains a pointer.
|
|
355
|
+
A 32-bit process and a 64-bit process cannot share a pointer.
|
|
356
|
+
|
|
357
|
+
```cpp
|
|
358
|
+
struct NPoints {
|
|
359
|
+
int n;
|
|
360
|
+
Point *points;
|
|
361
|
+
};
|
|
362
|
+
```
|
|
363
|
+
"""
|
|
364
|
+
|
|
365
|
+
_fields_ = ( # pyright: ignore[reportUnannotatedClassAttribute]
|
|
366
|
+
("n", ctypes.c_int),
|
|
367
|
+
("points", ctypes.POINTER(Point)),
|
|
368
|
+
)
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"""Communicates with the [cpp_lib][cpp-lib] library via the [Cpp32][] class that is running on a server."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
from msl.loadlib import Client64
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from collections.abc import Sequence
|
|
12
|
+
|
|
13
|
+
from .cpp32 import FourPoints
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Cpp64(Client64):
|
|
17
|
+
"""Communicates with a 32-bit C++ library."""
|
|
18
|
+
|
|
19
|
+
def __init__(self) -> None:
|
|
20
|
+
"""Communicates with a 32-bit C++ library via the server running [Cpp32][].
|
|
21
|
+
|
|
22
|
+
This class demonstrates how to communicate with a 32-bit C++ library if an
|
|
23
|
+
instance of this class is created within a 64-bit Python interpreter.
|
|
24
|
+
"""
|
|
25
|
+
# specify the name of the corresponding 32-bit server module, cpp32,
|
|
26
|
+
# which hosts the 32-bit C++ library -- cpp_lib32.
|
|
27
|
+
super().__init__("cpp32", append_sys_path=Path(__file__).parent)
|
|
28
|
+
|
|
29
|
+
def add(self, a: int, b: int) -> int:
|
|
30
|
+
"""Add two integers.
|
|
31
|
+
|
|
32
|
+
See the corresponding [Cpp32.add][msl.examples.loadlib.cpp32.Cpp32.add] method.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
a: First integer.
|
|
36
|
+
b: Second integer.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
The sum, `a + b`.
|
|
40
|
+
"""
|
|
41
|
+
reply: int = self.request32("add", a, b)
|
|
42
|
+
return reply
|
|
43
|
+
|
|
44
|
+
def subtract(self, a: float, b: float) -> float:
|
|
45
|
+
"""Subtract two floating-point numbers *('float' refers to the C++ data type)*.
|
|
46
|
+
|
|
47
|
+
See the corresponding [Cpp32.subtract][msl.examples.loadlib.cpp32.Cpp32.subtract] method.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
a: First floating-point number.
|
|
51
|
+
b: Second floating-point number.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
The difference, `a - b`.
|
|
55
|
+
"""
|
|
56
|
+
reply: float = self.request32("subtract", a, b)
|
|
57
|
+
return reply
|
|
58
|
+
|
|
59
|
+
def add_or_subtract(self, a: float, b: float, *, do_addition: bool) -> float:
|
|
60
|
+
"""Add or subtract two floating-point numbers *('double' refers to the C++ data type)*.
|
|
61
|
+
|
|
62
|
+
See the corresponding [Cpp32.add_or_subtract][msl.examples.loadlib.cpp32.Cpp32.add_or_subtract] method.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
a: First double-precision number.
|
|
66
|
+
b: Second double-precision number.
|
|
67
|
+
do_addition: Whether to add or subtract the numbers.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
`a + b` if `do_addition` is `True` else `a - b`.
|
|
71
|
+
"""
|
|
72
|
+
reply: float = self.request32("add_or_subtract", a, b, do_addition=do_addition)
|
|
73
|
+
return reply
|
|
74
|
+
|
|
75
|
+
def scalar_multiply(self, a: float, xin: Sequence[float]) -> list[float]:
|
|
76
|
+
"""Multiply each element in an array by a number.
|
|
77
|
+
|
|
78
|
+
See the corresponding [Cpp32.scalar_multiply][msl.examples.loadlib.cpp32.Cpp32.scalar_multiply] method.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
a: Scalar value.
|
|
82
|
+
xin: Array to modify.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
A new array with each element in `xin` multiplied by `a`.
|
|
86
|
+
"""
|
|
87
|
+
reply: list[float] = self.request32("scalar_multiply", a, xin)
|
|
88
|
+
return reply
|
|
89
|
+
|
|
90
|
+
def reverse_string_v1(self, original: str) -> str:
|
|
91
|
+
"""Reverse a string (version 1).
|
|
92
|
+
|
|
93
|
+
In this method Python allocates the memory for the reversed string
|
|
94
|
+
and passes the string to C++.
|
|
95
|
+
|
|
96
|
+
See the corresponding [Cpp32.reverse_string_v1][msl.examples.loadlib.cpp32.Cpp32.reverse_string_v1] method.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
original: The original string.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
The string reversed.
|
|
103
|
+
"""
|
|
104
|
+
reply: str = self.request32("reverse_string_v1", original)
|
|
105
|
+
return reply
|
|
106
|
+
|
|
107
|
+
def reverse_string_v2(self, original: str) -> str:
|
|
108
|
+
"""Reverse a string (version 2).
|
|
109
|
+
|
|
110
|
+
In this method C++ allocates the memory for the reversed string and passes
|
|
111
|
+
the string to Python.
|
|
112
|
+
|
|
113
|
+
See the corresponding [Cpp32.reverse_string_v2][msl.examples.loadlib.cpp32.Cpp32.reverse_string_v2] method.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
original: The original string.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
The string reversed.
|
|
120
|
+
"""
|
|
121
|
+
reply: str = self.request32("reverse_string_v2", original)
|
|
122
|
+
return reply
|
|
123
|
+
|
|
124
|
+
def distance_4_points(self, points: FourPoints) -> float:
|
|
125
|
+
"""Calculates the total distance connecting 4 [Point][msl.examples.loadlib.cpp32.Point]s.
|
|
126
|
+
|
|
127
|
+
See the corresponding [Cpp32.distance_4_points][msl.examples.loadlib.cpp32.Cpp32.distance_4_points] method.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
points: The points to use to calculate the total distance.
|
|
131
|
+
Since `points` is a struct that is a fixed size we can pass the
|
|
132
|
+
[ctypes.Structure][]{:target="_blank"} object directly from 64-bit Python to
|
|
133
|
+
the 32-bit Python. The [ctypes][]{:target="_blank"} module on the 32-bit server
|
|
134
|
+
can load the [pickle][]{:target="_blank"}d [ctypes.Structure][]{:target="_blank"}.
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
The total distance connecting the 4 points.
|
|
138
|
+
"""
|
|
139
|
+
reply: float = self.request32("distance_4_points", points)
|
|
140
|
+
return reply
|
|
141
|
+
|
|
142
|
+
def circumference(self, radius: float, n: int) -> float:
|
|
143
|
+
"""Estimates the circumference of a circle.
|
|
144
|
+
|
|
145
|
+
This method calls the `distance_n_points` function in [cpp_lib][cpp-lib].
|
|
146
|
+
|
|
147
|
+
See the corresponding [Cpp32.circumference][msl.examples.loadlib.cpp32.Cpp32.circumference] method.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
radius: The radius of the circle.
|
|
151
|
+
n: The number of points to use to estimate the circumference.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
The estimated circumference of the circle.
|
|
155
|
+
"""
|
|
156
|
+
reply: float = self.request32("circumference", radius, n)
|
|
157
|
+
return reply
|
|
Binary file
|
|
Binary file
|