Troubleshooting
Problem
The C++ compiler performs name mangling.
For example, it adds to the name of each C++ function a suffix encoding the parameter list, the return value of the function, and scoping information.
Resolving The Problem
The C++ compiler performs name mangling. For example, it adds to the name of each C++ function a suffix encoding the parameter list, the return value of the function, and scoping information. The purpose of name mangling is to allow for function overloading. This means that multiple functions can have the same name as long as the compiler can tell them apart based on their parameter lists and return values.
Consider the following C++ source:
#include <iostream>
using namespace std;
void print(int i){
cout << "Here is int " << i << endl;
}
void print(double f){
cout << "Here is float " << f << endl;
}
void print(char* c){
cout << "Here is char* " << c << endl;
}
int main(){
print(10);
print(10.10);
print("ten");
}
Function "print" is overloaded because of the multiple versions defined. The compiler accepts all versions and distinguishes among them based on their parameter lists (note that the return value of all three versions is void, but the parameter lists are all different). The mangled names of these functions are unique. This can be verified by compiling the above source using the CRTCPPMOD command and then using the DSPMOD MODULE(modulename) DETAIL(*PROCLIST) command. The output shows the following:Procedure list:
Procedure Name Procedure Type ARGOPT
print__Fi REGULAR *NO
print__Fd REGULAR *NO
print__FPc REGULAR *NO
.......
For the purposes of importing/exporting function names, C++ uses these mangled names. In C++, function definitions in exporting modules and prototypes in importing modules refer to the non-mangled name(s) (in this case, "print"). It is also important to note that C++ function names, whether mangled or not, are case sensitive. For information on how to correlate the mangled names of user-defined functions to the original names as declared, see source member DEMANGLE, file H, library QSYSINC.
These considerations are especially important when interfacing C++ with other languages. In particular, this document demonstrates how to handle name-mangling when interfacing C++ with ILE RPG. RPG prototypes for import and export must refer to the mangled name(s) exactly as generated by the C++ compiler. To see all mangled names imported/exported for a C++ module, compile the source code using the CRTCPPMOD command. Then, run the DSPMOD MODULE(modulename) DETAIL(*IMPORT *EXPORT) command. Note that the import screen from this command will also contain some unrelated default imports, for example:
Imported (unresolved) symbols:
Symbol Name Symbol Type ARGOPT
_C_exception_router PROCEDURE *UNKNOWN
__ls__7ostreamFd PROCEDURE *NO
__ls__7ostreamFPCc PROCEDURE *NO
flush__7ostreamFv PROCEDURE *NO
complicated_put__7ostreamFc PROCEDURE *NO
Q LE leDefaultEh PROCEDURE *UNKNOWN
_C_SIGABRT_ctl_action DATA
_C_SIGFPE_ctl_action DATA
_C_SIGILL_ctl_action DATA
_C_SIGINT_ctl_action DATA
_C_SIGSEGV_ctl_action DATA
_C_SIGTERM_ctl_action DATA
_C_SIGUSR1_ctl_action DATA
_C_SIGUSR2_ctl_action DATA
_C_SIGIO_ctl_action DATA
_C_SIGALL_ctl_action DATA
_C_SIGOTHER_ctl_action DATA
cout DATA
For C++ and ILE RPG to interface correctly, do the following:
| 1. | Compile each C++ source member first using the CRTCPPMOD command. |
| 2. | Run CL command DSPMOD MODULE(modulename) DETAIL(*IMPORT *EXPORT). Note the mangled names of the user-defined functions imported and exported. |
| 3. | Re-edit the ILE RPG source. On each prototype interfacing with C++, add keyword EXTPROC('.......'), where ....... is the mangled name imported by or exported from the C++ module. The name must be enclosed in single quotes and is case sensitive. |
| 4. | Compile each ILE RPG source member using the CRTRPGMOD command. |
| 5. | Bind the modules using the CRTPGM command to create the program. |
The following code samples illustrate our interfacing technique. The ILE RPG source is already re-edited per Steps 1, 2, 3 (the EXTPROC keywords added during re-editing are highlighted). To create the program, compile the RPG module (which is the entry point for the program), compile the C++ module, and bind the two modules together using the CRTPGM command.
ILE RPG Source CPPTORPG1:
**FREE
//
// This module contains the program entry point and works in conjunction
// with C++ module MOD_CPP.
//
//
// Definition for double-precision fields.
//
Dcl-S StdDouble Float(8);
//
// Symbolic name for the constant pi.
//
Dcl-C pi const(3.1415926535897932384626433833);
//
// rpgtocpp adds two double-precision numbers, displays the result,
// then returns the result to the caller.
// rpgtocpp is defined in MOD_CPP, and prototyped below.
// The mangled name of rpgtocpp is rpgtocpp__FdT1. The name specified
// in the prototype's EXTPROC keyword must exactly match the mangled
// name of the function as exported by C++.
//
Dcl-Pr rpgtocpp LIKE(StdDouble)
EXTPROC('rpgtocpp__FdT1');
pr_parm1 LIKE(StdDouble) VALUE;
pr_parm2 LIKE(StdDouble) VALUE;
End-Pr;
//
// cpptorpg multiplies two double-precision numbers, displays the result,
// then returns to the caller the product it computed.
// The mangled name of cpptorpg is cpptorpg__FdT1. The name specified
// in the prototype's EXTPROC keyword must exactly match the mangled
// name of the function as imported by C++.
//
Dcl-Pr cpptorpg1 LIKE(StdDouble)
EXTPROC('cpptorpg__FdT1');
pr_parm1 LIKE(StdDouble) VALUE;
pr_parm2 LIKE(StdDouble) VALUE;
End-Pr;
//
// Main Program
//
Dcl-S globalvar1 LIKE(StdDouble);
// Add the two parameters (the result is pi + pi)
globalvar1 = rpgtocpp(pi:pi);
*inlr = *on;
//
// Procedure called from C++ to multiply two parameters.
//
Dcl-Proc cpptorpg1 EXPORT;
Dcl-Pi cpptorpg1 LIKE(StdDouble);
parm1 LIKE(StdDouble) VALUE;
parm2 LIKE(StdDouble) VALUE;
End-Pi;
//
Dcl-S var1 LIKE(StdDouble);
//
// Multiply the two parameters.
//
var1 = parm1 * parm2;
//
// Display result.
//
Dsply parm1;
Dsply '*';
Dsply parm2;
Dsply '=';
Dsply var1;
//
// Return result to the caller.
//
Return var1;
End-Proc cpptorpg1;
C++ Source CPPINVOKE1:
/*
This module works in conjunction with RPG module MOD_RPG, which contains the
program entry point.
*/
#include <iostream.h>
using namespace std;
/*
cpptorpg multiplies two double-precision numbers, displays the result, then
returns the result to the caller.
cpptorpg is defined in MOD_RPG, and prototyped below. While C++ views it
as a function, cpptorpg is defined in ILE RPG as a subprocedure.
The mangled name of cpptorpg is cpptorpg__FdT1, and the RPG code is
designed to export the mangled name for use by C++.
*/
double cpptorpg(double parm1, double parm2);
/*
rpgtocpp adds two double-precision numbers, displays the result, then
calls cpptorpg with the same two parameters. rpgtocpp then returns to the
caller the sum it computed.
The mangled name of rpgtocpp is rpgtocpp__FdT1, and the RPG code is
designed to import the mangled name as exported by C++.
*/
double rpgtocpp(double parm1, double parm2){
double var1, var2;
var1 = parm1 + parm2;
cout << parm1 << " + " << parm2 << " = " << var1 << endl;
/*
/* var2 receives the return value from cpptorpg, but the value is not used in
this function.
*/
var2 = cpptorpg(parm1, parm2);
return(var1);
}
Compile using:
CRTRPGMOD MODULE(<yourlib>/CPPTORPG1) SRCFILE(<yourlib>/QRPGLESRC) SRCMBR(CPPTORPG1)
CRTCPPMOD MODULE(<yourlib>/CPPINVOKE1) SRCFILE(<yourlib>/QCSRC) SRCMBR(CPPINVOKE1)
CRTPGM PGM(<yourlib>/TESTCPP) MODULE(<yourlib>/CPPTORPG1 <yourlib>/CPPINVOKE1)
Call from command line:
Call from command line:
> call testcpp
DSPLY +3.141592653589793E+000
DSPLY *
DSPLY +3.141592653589793E+000
DSPLY =
DSPLY +9.869604401089358E+000
DSPLY +3.141592653589793E+000
DSPLY *
DSPLY +3.141592653589793E+000
DSPLY =
DSPLY +9.869604401089358E+000
[{"Type":"MASTER","Line of Business":{"code":"LOB68","label":"Power HW"},"Business Unit":{"code":"BU070","label":"IBM Infrastructure"},"Product":{"code":"SWG60","label":"IBM i"},"ARM Category":[{"code":"a8m0z0000000CHtAAM","label":"Programming ILE Languages"}],"ARM Case Number":"","Platform":[{"code":"PF012","label":"IBM i"}],"Version":"All Versions"}]
Historical Number
25971910
Was this topic helpful?
Document Information
Modified date:
27 November 2024
UID
nas8N1017083