C++: Call a Foreign-Language Function

Bjarne-stroustrup
 

Show how a foreign language function can be called from the language.

As an example, consider calling functions defined in the C language. Create a string containing “Hello World!” of the string type typical to the language. Pass the string content to C‘s strdup. The content can be copied if necessary. Get the result from strdup and print it using language means. Do not forget to free the result of strdup (allocated in the heap).

Notes:

  • It is not mandated if the C run-time library is to be loaded statically or dynamically. You are free to use either way.
  • C++ and C solutions can take some other language to communicate with.
  • It is not mandatory to use strdup, especially if the foreign function interface being demonstrated makes that uninformative.

While calling C functions from C++ is generally almost trivial, strdup illustrates some fine point in communicating with C libraries. However, to illustrate how to generally use C functions, a C function strdup1 is used, which is assumed to have the same interface and behaviour as strdup, but cannot be found in a standard header.

In addition, this code demonstrates a call to a FORTRAN function defined as

FUNCTION MULTIPLY(X, Y)
DOUBLE PRECISION MULTIPLY, X, Y

Note that the calling convention of FORTRAN depends on the system and the used FORTRAN compiler, and sometimes even on the command line options used for the compiler; here, GNU Fortran with no options is assumed.

#include <cstdlib>  // for C memory management
#include <string>   // for C++ strings
#include <iostream> // for output

// C functions must be defined extern "C"
extern "C" char* strdup1(char const*);

// Fortran functions must also be defined extern "C" to prevent name
// mangling; in addition, all fortran names are converted to lowercase
// and get an undescore appended. Fortran takes all arguments by
// reference, which translates to pointers in C and C++ (C++
// references generally work, too, but that may depend on the C++
// compiler)
extern "C" double multiply_(double* x, double* y);

// to simplify the use and reduce the probability of errors, a simple
// inline forwarder like this can be used:
inline double multiply(double x, double y)
{
	return multiply_(&x, &y);
}

int main()
{
	std::string msg = "The product of 3 and 5 is ";

	// call to C function (note that this should not be assigned
	// directly to a C++ string, because strdup1 allocates memory, and
	// we would leak the memory if we wouldn't save the pointer itself
	char* msg2 = strdup1(msg.c_str());

	// C strings can be directly output to std::cout, so we don't need
	// to put it back into a string to output it.
	std::cout << msg2;

	// call the FORTRAN function (through the wrapper):
	std::cout << multiply(3, 5) << std::endl;

	// since strdup1 allocates with malloc, it must be deallocated with
	// free, not delete, nor delete[], nor operator delete
	std::free(msg2);
}

SOURCE

Content is available under GNU Free Documentation License 1.2.