Skip to content

Commit 65a9851

Browse files
PeterTurcanalandefreitas
authored andcommitted
Other Languages (Python, C#, Java) Q/A to FAQ
Code blocks fixed
1 parent cf6c69d commit 65a9851

File tree

1 file changed

+257
-0
lines changed

1 file changed

+257
-0
lines changed

user-guide/modules/ROOT/pages/faq.adoc

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,263 @@ Correct - backwards-compatibility should be maintained.
303303
+
304304
An exact timeline requires issues to be resolved, though later in 2024 is the current plan-of-record.
305305

306+
== Other Languages
307+
308+
. *Have developers written applications in languages such as Python that have successfully used the Boost libraries?*
309+
+
310+
Yes, developers have successfully used Boost libraries in applications written in languages other than pass:[C++] by leveraging language interoperability features and creating bindings or wrappers.
311+
+
312+
The most notable example is the use of boost:python[], a library specifically designed to enable seamless interoperability between pass:[C++] and Python. boost:python[] allows developers to expose pass:[C++] classes, functions, and objects to Python, enabling the use of the libraries from Python code. This has been used extensively in scientific computing, game development, and other fields where the performance of pass:[C++] is combined with the ease of Python.
313+
+
314+
Here is an example, wrapping a pass:[C++] class for use with boost:python[] and including exception handling:
315+
+
316+
[source,cpp]
317+
----
318+
// my_class.cpp
319+
#include <boost/python.hpp>
320+
#include <iostream>
321+
#include <stdexcept>
322+
323+
class MyClass {
324+
public:
325+
void hello() {
326+
std::cout << "Hello from C++!" << std::endl;
327+
}
328+
329+
int add(int a, int b) {
330+
return a + b;
331+
}
332+
333+
void throw_exception() {
334+
throw std::runtime_error("An error occurred in C++ code");
335+
}
336+
};
337+
338+
// Function to translate C++ exceptions to Python exceptions
339+
void translate_runtime_error(const std::runtime_error& e) {
340+
PyErr_SetString(PyExc_RuntimeError, e.what());
341+
}
342+
343+
BOOST_PYTHON_MODULE(my_module) {
344+
using namespace boost::python;
345+
// Register the exception translator
346+
register_exception_translator<std::runtime_error>(translate_runtime_error);
347+
348+
class_<MyClass>("MyClass")
349+
.def("hello", &MyClass::hello)
350+
.def("add", &MyClass::add)
351+
.def("throw_exception", &MyClass::throw_exception);
352+
}
353+
354+
----
355+
+
356+
You need to compile this pass:[C++] code into a shared library that Python can load. Here's an example command for compiling using g++ on Linux. Make sure to adjust the Python include path and boost:python[] library name according to your system's configuration:
357+
+
358+
----
359+
g++ -shared -fPIC -I/usr/include/python3.8 -lboost_python38 -o my_module.so my_class.cpp
360+
----
361+
+
362+
Next, write the Python code that will use the wrapped class:
363+
+
364+
[source,python]
365+
----
366+
# test_my_module.py
367+
import my_module
368+
369+
# Create an instance of MyClass
370+
my_class_instance = my_module.MyClass()
371+
372+
# Call the hello method
373+
my_class_instance.hello()
374+
375+
# Call the add method
376+
result = my_class_instance.add(3, 4)
377+
print(f"The result of adding 3 and 4 is: {result}")
378+
379+
# Call the throw_exception method and handle the exception
380+
try:
381+
my_class_instance.throw_exception()
382+
except RuntimeError as e:
383+
print(f"Caught an exception: {e}")
384+
385+
----
386+
+
387+
Ensure that the shared library (`my_module.so`) is in the same directory as your Python script or in a directory that's included in the Python module search path. Then run the script:
388+
+
389+
----
390+
python3 test_my_module.py
391+
----
392+
+
393+
When you run the Python script, you should see the following output:
394+
+
395+
----
396+
Hello from C++!
397+
The result of adding 3 and 4 is: 7
398+
Caught an exception: An error occurred in C++ code
399+
----
400+
+
401+
Note:: By registering an exception translator, you can ensure that pass:[C++] exceptions are correctly translated into Python exceptions, making your pass:[C++] library more robust and easier to use from Python.
402+
403+
. *What real world applications have combined Python with the Boost libraries?*
404+
+
405+
Here are some examples:
406+
+
407+
* https://www.blender.org/[Blender] is a widely-used open-source 3D creation suite. It supports the entirety of the 3D pipeline, including modeling, rigging, animation, simulation, rendering, compositing, and motion tracking. Blender uses Boost libraries for various purposes, including memory management, string manipulation, and other utility functions. Blender's Python API, which allows users to script and automate tasks, integrates with pass:[C++] code using boost:python[].
408+
+
409+
* https://pytorch.org/[PyTorch] is an open-source machine learning library based on the Torch library. It is used for applications such as natural language processing and computer vision. PyTorch uses several Boost libraries to handle low-level operations efficiently. boost:python[] is used to create bindings between pass:[C++] and Python, allowing PyTorch to provide a seamless interface for Python developers.
410+
+
411+
* https://opencv.org/[OpenCV] (Open Source Computer Vision Library) is an open-source computer vision and machine learning software library. OpenCV's Python bindings use boost:python[] to interface between the pass:[C++] core and Python. This allows Python developers to use OpenCV's powerful pass:[C++] functions with Python syntax.
412+
+
413+
* https://docs.enthought.com/canopy/2.1/index.html[Enthought Canopy] is a comprehensive Python analysis environment and distribution for scientific and analytic computing. It includes a Python distribution, an integrated development environment (IDE), and many additional tools and libraries.
414+
415+
. *Are there some solid examples of real world applications that have combined C# with the Boost libraries?*
416+
+
417+
Here are some great examples:
418+
+
419+
* In the world of game development, several projects use pass:[C++] for performance-critical components and C# for scripting and higher-level logic. The Boost libraries are often used in the pass:[C++] components, in particular to leverage their algorithms, and data structures. https://unity.com/[Unity] allows the use of native plugins written in pass[C++]. These plugins can use Boost libraries for various functionalities, such as pathfinding algorithms or custom data structures, and then be called from C# scripts within Unity.
420+
+
421+
* Financial applications often require high performance and reliability. They may use pass:[C++] for core processing and Boost libraries for tasks like date-time calculations, serialization, and multithreading. C# is used for GUI and integration with other enterprise systems. Trading platforms and risk management systems sometimes use Boost libraries for backend processing and interoperate with C# components for the user interface and data reporting.
422+
+
423+
* Scientific computing applications that need high-performance computation often use pass:[C++] for core algorithms. C# is great for visualization, user interaction, and orchestration. Computational chemistry and physics applications sometimes use Boost for numerical computations and data handling, while C# provides the tools for managing simulations and visualizing results.
424+
425+
. *Can I see some sample code of how to wrap Boost functions to be available for use in a C# app?*
426+
+
427+
The following code shows how to create a wrapper for a pass:[C++] class that uses Boost, and then calls this from a C# application. The handling of return values and exceptions are shown too:
428+
+
429+
[source,cpp]
430+
----
431+
// my_class.cpp
432+
#include <boost/algorithm/string.hpp>
433+
#include <iostream>
434+
#include <stdexcept>
435+
#include <string>
436+
437+
class MyClass {
438+
public:
439+
std::string to_upper(const std::string& input) {
440+
if (input.empty()) {
441+
throw std::runtime_error("Input string is empty");
442+
}
443+
return boost::to_upper_copy(input);
444+
}
445+
};
446+
----
447+
+
448+
Next, create a wrapper to expose the class to .NET:
449+
+
450+
[source,cpp]
451+
----
452+
// MyClassWrapper.cpp
453+
#include "my_class.cpp"
454+
#include <string>
455+
456+
public ref class MyClassWrapper {
457+
private:
458+
MyClass* instance;
459+
460+
public:
461+
MyClassWrapper() {
462+
instance = new MyClass();
463+
}
464+
465+
~MyClassWrapper() {
466+
this->!MyClassWrapper();
467+
}
468+
469+
!MyClassWrapper() {
470+
delete instance;
471+
}
472+
473+
System::String^ ToUpper(System::String^ input) {
474+
try {
475+
std::string nativeInput = msclr::interop::marshal_as<std::string>(input);
476+
std::string result = instance->to_upper(nativeInput);
477+
return gcnew System::String(result.c_str());
478+
} catch (const std::runtime_error& e) {
479+
throw gcnew System::Runtime::InteropServices::ExternalException(gcnew System::String(e.what()));
480+
}
481+
}
482+
};
483+
----
484+
+
485+
Now create the C# application that uses the wrapper:
486+
+
487+
[source,csharp]
488+
----
489+
// Program.cs
490+
using System;
491+
492+
class Program {
493+
static void Main() {
494+
MyClassWrapper myClass = new MyClassWrapper();
495+
496+
try {
497+
string result = myClass.ToUpper("hello world");
498+
Console.WriteLine("Result: " + result);
499+
500+
// Test with an empty string to trigger the exception
501+
result = myClass.ToUpper("");
502+
Console.WriteLine("Result: " + result);
503+
} catch (System.Runtime.InteropServices.ExternalException e) {
504+
Console.WriteLine("Caught an exception: " + e.Message);
505+
}
506+
}
507+
}
508+
----
509+
+
510+
Compile the C++ code into a DLL:
511+
+
512+
----
513+
cl /c /EHsc my_class.cpp
514+
----
515+
+
516+
Compile the wrapper:
517+
+
518+
----
519+
cl /clr /EHsc /I"path\to\boost" MyClassWrapper.cpp my_class.obj /link /OUT:MyClassWrapper.dll
520+
----
521+
+
522+
Finally, create a C# project (say, using Visual Studio), add a reference to the `MyClassWrapper.dll`, then build and run the application:
523+
+
524+
----
525+
Result: HELLO WORLD
526+
Caught an exception: Input string is empty
527+
----
528+
529+
. *Does the Java Native Interface (JNI) work with the Boost libraries?*
530+
+
531+
Through the use of the Java Native Interface (JNI) or Java Native Access (JNA), developers can call Boost libraries from Java applications. It involves creating native methods in Java that are implemented in pass:[C++] and using Boost libraries as part of those implementations. Here is a simple example (without error handling or return values):
532+
+
533+
[source,cpp]
534+
----
535+
// C++ implementation
536+
#include <jni.h>
537+
#include "MyClass.h"
538+
539+
JNIEXPORT void JNICALL Java_MyClass_hello(JNIEnv* env, jobject obj) {
540+
MyClass myClass;
541+
myClass.hello();
542+
}
543+
----
544+
+
545+
[source,java]
546+
----
547+
// Java class
548+
public class MyClass {
549+
static {
550+
System.loadLibrary("myclass");
551+
}
552+
553+
private native void hello();
554+
555+
public static void main(String[] args) {
556+
new MyClass().hello();
557+
}
558+
}
559+
----
560+
561+
Note:: Similar techniques can be applied to other languages, such as R, Ruby, Perl, and Lua, using their respective foreign function interfaces (FFI) or binding libraries.
562+
306563
== Releases
307564

308565
. *How do I download the latest libraries?*

0 commit comments

Comments
 (0)