|
Rust support for ChartDirector |
Posted by CHRIS HAIDINYAK on Mar-17-2024 23:30 |
|
Hi,
Any thoughts whether Rust will be supported; it seems that with the US govt suggesting C/C++ be deprecated, Rust is a viable alternative with the support of Linux. Thanks.
Best,
Chris |
Re: Rust support for ChartDirector |
Posted by Peter Kwan on Mar-19-2024 17:57 |
|
Hi CHRIS,
Last time we look at Rust, we found that it does not have a stable ABI, That means code generated by different Rust complier versions are not compatible. As a result, we cannot release a precompiled library in Rust, as it may not be compatible with the user's Rust compiler. Everything in Rust must be released in source code, so they can be compiled with the same compiler.
To be fair, C++ has the same problem as Rust. The C++ part of ChartDirector is in fact released in source code. The C++ part is a wrapper for the ChartDirector C API implemented in the ChartDirector DLL/shared object. C has a standardized ABI and is used by the OS itself for its API.
I am sure there must be a way for Rust to call C code, otherwise it will not be able access the OS (such as open network sockets, access the GUI subsystem, ...). Unluckily, due to our resource constraint, currently we have no plan to write a Rust wrapper for the ChartDirector C API. I am hoping someone familiar with Rust would be able to do this.
Best Regards
Peter Kwan |
Re: Rust support for ChartDirector |
Posted by CHRIS HAIDINYAK on Mar-20-2024 20:24 |
|
Hi,
Thanks for the thoughtful reply. If you could outline the steps and files you think would need to be modified into Rust and any pitfalls you think exist; I could attempt it. Thank you.
Best,
Chris |
Re: Rust support for ChartDirector |
Posted by Peter Kwan on Mar-20-2024 22:58 |
|
Hi CHRIS,
The ChartDirector C API is declared in "bchartdir.h". The total API contains over 1000 entries, so it is not a small effort to port all of them.
The C++ wrapper is implemented in "chartdir.h". If you are familiar with both C++ and C, the C++ wrapper should be very useful for porting to Rust and it contains the fine details on how to wrap the API.
In brief, consider the simplest class in ChartDirector, which is for random number generation in our sample code:
https://www.advsofteng.com/doc/cdcpp.htm#RanSeries.htm
The following is the explanation of the wrapper code:
class RanSeries
{
// The C pointer to the object
RanSeriesInternal *ptr;
public :
// Constructor maps to a C "create" function which returns a C pointer
RanSeries(int seed) : ptr(CRanSeries_create(seed)) {}
// Destructor maps to a C "destroy" function that frees the memory of the C pointer
~RanSeries() { CRanSeries_destroy(ptr); }
// The getSeries method is mapped to the C "getSeries" function. In C, it is not
// allowed to return an object such as DoubleArray. So the C API returns the
// object data in the argument list (as ret and retLen) and the actual DoubleArray
// is constructed in the C++ code.
DoubleArray getSeries(int len, double minValue, double maxValue)
{
const double *ret; int retLen;
CRanSeries_getSeries(ptr, len, minValue, maxValue, &ret, &retLen);
return DoubleArray(ret, retLen);
}
......
}
For most of the cases, the mapping is straight forward and is just one line of code. But in some cases (like the getSeries above), more code is needed to translate between C and C++ data types.
Some API returns a C++ object pointer. The C API can only return a C pointer. The wrapper code needs to create a new C++ object to wrap the C pointer. The wrapper code needs to keep track of all such new objects so that they can be deleted later to avoid memory leak.
Best Regards
Peter Kwan |
|