I want to call Rust from GnuCOBOL. I've copied the code from the first example in Can GnuCOBOL interface with Rust? from Brian Tiffin's GNUCobol FAQ as a test but got an error when running it.
Expected:
$ make -B
rustc --crate-type=dylib called.rs
LD_RUN_PATH=. cobc -xj caller.cob -L. -lcalled
:Hello, world:
Actual:
$ make -B
rustc --crate-type=dylib called.rs
LD_RUN_PATH=. cobc -xj caller.cob -L. -lcalled
libcob: error: module 'hello_rust' not found
make: *** [makefile:5: caller] Error 1
I get the same error after compiling both files from the command line, then using $ ./caller
.
The syntax seems correct based on the cobc
man page and the linkage sections of the GnuCOBOL manual and Rust reference. I've tried $ ./caller COB_LIBRARY_PATH=.
as described in the GnuCOBOL manual, but it doesn't make a difference. The Rust source compiles to a library as expected, but the COBOL doesn't find it.
Using $ cobcrun caller
instead displays libcob: error: module 'caller' not found
.
This question about a similar error is about statically linking multiple COBOL source files, which works fine, and this question about a similar error seems to be an issue with X"AF"
, which isn't used here. Statically linking C source with Jay Moseley's C Wrapper for Calling Library Function example works as expected. Statically linking Rust source isn't supported.
Software Versions:
The issue seems to be that the COBOL caller
executable is trying to dynamically load a library named hello_rust.so
instead of libcalled.so
at runtime.
The easy fix without modifying anything is to just create a symlink:
$ ln -s libcalled.so hello_rust.so
Alternatively, adding -fstatic
to the cobc
command should statically link the Rust library at compilation, eliminating the dynamic library runtime calls.
The example Makefile
can be updated to look like this:
# GnuCOBOL and Rust
.RECIPEPREFIX = >
caller: caller.cob libcalled.so
> LD_RUN_PATH=. cobc -fstatic -xj caller.cob -L. -lcalled
libcalled.so: called.rs
> rustc --crate-type=dylib called.rs
For reference, we can investigate what the executable is doing via strace to see what system calls the COBOL runtime is making -- and in our case -- what files it's failing to find.
$ strace ./caller 2>&1 | grep hello_rust
access("./hello_rust.so", R_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib64/gnucobol/hello_rust.so", R_OK) = -1 ENOENT (No such file or directory)
write(2, "module 'hello_rust' not found", 29module 'hello_rust' not found) = 29