I have read about several methods to combine C and C++ codes, however, I'm still confused on how to proceed in my case. Here is my problem:
I have a relatively large amount of C code (consisting of various .c
and .h
files) which is used to model solids in finite and discrete elements. This code has relatively short and simple main function with a for
loop in which various other functions (from other files) are called sequentially. This code works fine when compiled in both Unix (icc compiler) and Visual Studio.
I have other code in C++ that solves molecular dynamics interactions. This code also consists of various files and runs fine in both Unix (icpc compiler) and VS. Both are stand alone programs with their own input and output set of files.
What I need to do is to run both programs in such way that my C program "calls" the C++ code in its main loop. Some information needs to be passed both ways between the two codes, which may be in the form of arrays (or pointers).
What is the simplest way to do this?
In particular, I have multiple questions based on recommendations I have read:
- Should I wrap my C header files with
extern "C" {}
? - Should I use
extern "C"
in my C functions? - Or should I use
extern "C"
in my C++ files? (headers? functions? all of them? or only those I need to call from the C program?) - In understand I can not have two
main
functions. Can I simply rename my C++main
function? - When compiling in unix, should I use both C (icc) and C++ (icpc) compilers for different files? or just the C++ compiler?
- Could it be an option (to simplify things) to convert my
main
function from C to C++? - If I don't need to pass information of classes between the two programs, do I need to do anything about them?
- In what order do you suggest this problem to be tackled? (e.g. first have my C program compiled by C++ compiler; second, compile both codes together with no links; third, link the codes; fourth, rename
main
in C++ and have it "called" by my C code; fifth, implement the transfer of information?) - Finally, there are some macros in each program, which are repeated (same name, same implementation). Is there a conflict with this? Should I only keep one set of macros?
Sorry for the long text and multiple questions. I am relatively new to C and even newer to C++, so even my vocabulary on these programs is limited.
Thanks for the help. Any hints will be appreciated. If you need additional information, please let me know.
Here is the 'main' function of my C code:
#include "Yproto.h"
void show_time_info(YDC ydc,CHR Ystage[3]);
main(argc, argv)
INT argc; char **argv;
{ CHR c1name[300]; /* name of the problem i.e. input file */
struct YD_struct yd; /* Y database */
YDC ydc=&(yd.ydc); /* Y control database */
YDE yde=&(yd.yde); /* Y element database */
YDI ydi=&(yd.ydi); /* Y interaction database */
YDN ydn=&(yd.ydn); /* Y node database */
YDB ydb=&(yd.ydb); /* Y borehole database */
YDS yds=&(yd.yds); /* Y source (inter. fluid) database */
YDO ydo=&(yd.ydo); /* Y output database */
YDPE ydpe=&(yd.ydpe); /* Y property database for elements */
YDPN ydpn=&(yd.ydpn); /* Y property database for nodes (BC) */
YDPJ ydpj=&(yd.ydpj); /* Y property database for joints */
YDPM ydpm=&(yd.ydpm); /* Y property database for meshing */
INT Tctrlc, itimes=0;
CHR *p=NULL;
/* get name of the problem */
if(argv[1]!=NULL)
{ CHRcpy(c1name,argv[1]);
}
else
{ CHRwcr(stdout);
CHRw(stdout," please define input file names: "); CHRwcr(stdout);
CHRw(stdout," >");
fgets(c1name,sizeof(c1name),stdin);
if((p=strrchr(c1name,'\n'))!=NULL) *p = '\0';
}
strcpy(ydc->cfiname, c1name); ydc->cfiname[255]='\0';
ydc->finp=FILENULL; ydc->fcheck=FILENULL;
/* Process while any input */
while(Yrd(c1name,&yd)>0)
{ itimes=itimes+1;
CHRw(stdout,"NEW INPUT: "); CHRw(stdout, c1name); CHRwcr(stdout);
if(Ycheck(&yd)<0) break; date_and_time(ydc->cruntime); timestamp();
CHRw(stdout, "Start calculating ...\n");
omp_set_num_threads(8);
for(ydc->ncstep=ydc->ncstep;ydc->ncstep<ydc->mcstep;ydc->ncstep++)
{ show_time_info(ydc,"Ymd"); /* show time information */
Ymd(ydc,yde,ydi,ydn,ydpe,ydpn,ydpm); /* mesh elements */
/********** HERE IS WHERE I WOULD LIKE TO CALL MY C++ PROGRAM ***************/
Yfd(ydc,yde,ydn,ydi,ydo,ydpe,ydpn,ydpj); /* nodal forces */
Ybor(ydc,yde,ydn,ydb,yds,ydpe,ydpj,ydpn); /* borholes, inter. fluid */
Ycd(ydc,yde,ydi,ydn,ydpe,ydpn); /* contact detection */
Yid(ydc,yde,ydi,ydn,ydo,ydpe,ydpn, ydpj,ydpm); /* interaction */
Yod(c1name,&yd); /* output results */
Ysd(ydc,yde,ydn,ydo,ydpe,ydpn ); /* solve equations */
Yfrd(ydc,yde,ydi,ydn,ydpe,ydpn,ydpj,ydpm); /* fracture */
ydc->dctime=ydc->dctime+ydc->dcstec; /* update time */
/* CTRL-C Interruption */
Tctrlc = enablc(ydc->dctime, ydc->ncstep, ydc->mcstep);
if(Tctrlc!=1) break;
}
}
/* Termination */
CHRw(stderr," ***** Y HAS ORDERLY FINISHED *****"); CHRwcr(stderr);
CHRw(stderr,"Press a key to continue"); CHRwcr(stderr);
getchar();
}
UPDATE 24 HOURS AFTER ANSWERS
I followed the recommendations as per provided answers and the solution to my problem turned out to be much simpler than originally thought (although I did have to explore several options before getting it working). The best part is that it works in both Unix and Visual Studio. Here is the summary of steps I took:
Convert my main C file to C++. For this, rename the file containing the
main
function of my C code with a .cpp extension (changed from Y.c to Y.cpp) and change the beginning of themain
function from:main(argc, argv) INT argc; char **argv;
to
int main(int argc,char **argv)
in order to make it C++ 'friendly'. (Note: I understand renaming the file to .cpp is not essential, but I think it's better to do it for clarity).
Wrap all my C header files with
#ifdef __cplusplus extern "C" { #endif
at the beginning, and
#ifdef __cplusplus } #endif
at the end.
Change the name of my
main
C++ function and (temporarily) use no arguments. I named itint Ynano()
.Create a new header file called Y_NANO.h (Y_NANO.cpp is the name of the file containing the originally main C++ function) with the line:
int Ynano();
Include the new header in both Y.cpp and Y_NANO.cpp:
#include "Y_NANO.h"
Call the function
Ynano()
from themain
function in Y.cpp.To compile in Visual Studio, simply put all the source files in the same folder and create a new project. In Unix, I followed the steps given here.
These steps will only make the programs run together, with no transfer of information between them. To transfer information between the programs, it is necessary to include some parameters as arguments of Ynano()
, but that's another story.
Some final comments:
- The problem of having repeated macros in different header files does not seem to be a real problem, as long as no file includes both headers (I didn't need to do anything about this).
- Thanks to all who provided answers. They were really helpful. The chosen answer was selected on the basis of completeness, but others were just as good. I hope the thread helps others to do their job, as many other threads have helped me to do the same.