我已经阅读了几种组合 C 和 C++ 代码的方法,但是,我仍然对如何进行我的案例感到困惑。这是我的问题:
我有相对大量的 C 代码(由各种 .c
和 .h
文件组成)用于模拟有限和离散元素中的实体。这段代码有一个相对简短和简单的主函数,带有 for
循环中按顺序调用各种其他函数(来自其他文件)。此代码在 Unix(icc 编译器)和 Visual Studio 中编译时都可以正常工作。
我在 C++ 中有其他代码可以解决分子动力学相互作用。此代码还包含各种文件,并且在 Unix(icpc 编译器)和 VS 中都可以正常运行。两者都是具有自己的输入和输出文件集的独立程序。
我需要做什么是以这样的方式运行这两个程序,即我的 C 程序在其主循环中“调用”C++ 代码。有些信息需要在两个代码之间双向传递,可能是数组(或指针)的形式。
什么是最简单的方法来做到这一点?
特别是,根据我阅读的建议,我有多个问题:
extern "C" {}
包装我的 C 头文件吗? ? extern "C"
在我的 C 函数中? extern "C"
在我的 C++ 文件中? (头文件?函数?所有这些?还是只有那些我需要从 C 程序调用的?)main
职能。我可以简单地重命名我的 C++ main
功能? main
从 C 到 C++ 的函数? main
并让我的 C 代码“调用”它;第五,实现信息传递?)抱歉,文字太长,问题多。我对 C 比较陌生,甚至对 C++ 也比较陌生,所以我在这些程序上的词汇量也是有限的。
谢谢您的帮助。任何提示将不胜感激。如果您需要其他信息,请告诉我。
这是我的 C 代码的“主要”函数:
#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();
}
答复后 24 小时更新
我按照提供的答案遵循了建议,结果我的问题的解决方案比原先想象的要简单得多(尽管在让它工作之前我确实必须探索几个选项)。最好的部分是它适用于 Unix 和 Visual Studio。以下是我采取的步骤的总结:
main
的文件。我的 C 代码的函数带有 .cpp 扩展名(从 Y.c 更改为 Y.cpp)并更改 main
的开头功能来自:main(argc, argv)
INT argc; char **argv;
到
int main(int argc,char **argv)
为了使其 C++“友好”。 (注意:我知道将文件重命名为 .cpp 不是必需的,但我认为为了清楚起见最好这样做)。
#ifdef __cplusplus
extern "C" {
#endif
一开始,和
#ifdef __cplusplus
}
#endif
最后。
main
C++ 函数和(暂时)不使用参数。我给它取名 int Ynano()
. int Ynano();
#include "Y_NANO.h"
Ynano()
来自 main
Y.cpp 中的函数。 这些步骤只会使程序一起运行,而不会在它们之间传递信息。为了在程序之间传递信息,需要包含一些参数作为
Ynano()
的参数。 ,但那是另一回事了。最后的一些评论:
最佳答案
1) Should I wrap my C header files with
extern "C" {}
?2) Should I use
extern "C"
in my C functions?
仅当您打算
#include
某些 C++ 源文件中的 C 头文件,即,如果您想从您的 C++ 代码中调用 C 函数之一。使 C 头文件在 C++ 中可用的典型方法是这样的:#ifndef MY_C_HEADER_H
#define MY_C_HEADER_H
#ifdef __cplusplus
extern "C" {
#endif
/* All the original content of the C header */
#ifdef __cplusplus
}
#endif
#endif
如果不想修改header,也可以简单的应用
extern "C"
将其包含在 C++ 源文件中时,从头文件的外部:// in my_source.cpp (or some C++ header file):
extern "C" {
#include "my_c_header.h"
}
注意:根本不推荐使用该解决方案,也不是长期/可维护的解决方案,它只是一个快速而肮脏的“让它工作”的解决方案,经常失败,但有时会奏效,具体取决于 C header 看起来像(C header 不需要包含许多其他 header ,一般不应该包含,但有些作者没有这样做的常识)。
extern "C"
的原因是禁用 C++ 名称修改,即告诉编译器应该编译函数以对应于未修改的符号和/或应该在未修改的符号表中查找(链接到它们时)。因此,规则很简单,您想要编译成可从 C 代码(或任何其他语言)调用的库的任何 C++ 函数都需要声明为 extern "C"
.您在 C++ 代码中调用但链接到从 C(或任何其他语言)编译的库的任何函数声明必须是 extern "C"
以及。3) 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?)
如果你想从你的 C 代码中调用一些 C++ 函数,那么这些特定的函数必须声明为
extern "C"
编译该 C++ 代码时。在声明这些函数的 C 头文件中(为了从 C 代码调用它们),不需要 extern "C"
(它总是隐含在 C 中)。4) In understand I can not have two 'main' functions. Can I simply rename my C++ 'main' function?
两个主要功能的目的是什么?这是不允许的,也没有用。您仍然可以只拥有一个开始和结束的“程序”,即一个主要功能。您必须选择其中一个主要功能,并添加您想要的任何额外步骤(调用另一个库)。换句话说,您必须“合并”主要功能。
5) When compiling in unix, should I use both C (icc) and C++ (icpc) compilers for different files? or just the C++ compiler?
您使用 C 编译器编译 C 代码,使用 C++ 编译器编译 C++ 代码。无论如何,大多数构建系统(cmake、make 等)都会自动执行此操作。从技术上讲,您可以尝试使用 C++ 编译器编译 C 代码,但不要指望它立即工作,甚至根本无法轻松使其工作,恕我直言,不值得付出努力。
6) Could it be an option (to simplify things) to convert my main function from C to C++?
那是一种选择。你的包含 C main 函数的源文件看起来比较简单,它包含一个 C 头文件并且有一个相当简单的 main 函数。如果是这样,这将不难在 C++ 编译器上进行编译(除非它包含的 C 头文件是许多其他 C 头文件,这是不好的做法,但很可能)。您需要使用
extern "C" { }
来包装包含的 C 头文件。如上图所示。然后,您可以尝试在 C++ 编译器中编译它(仅包含 main 函数的源文件),并使用 C 编译器编译其余的 C 代码,然后将整个内容链接在一起。如果立即生效,那就太好了,您可以开始将该 C main 函数与来自其他库的 C++ main 函数合并,然后就可以了。否则,通常的选择是弄清楚您需要 C++ 代码做什么。然后,使用 C++ 库在 C++ 中创建一个 C 友好的函数(无类等)来执行这些操作。然后,创建一个声明该函数的头文件,使用
extern "C"
说明符(仅在 C++ 下编译时 ( __cplusplus
)),并确保此头文件不包含任何其他 C++ 头文件(不是标准头文件,不是来自 C++ 库的任何其他头文件)。最后,在您拥有 main 函数的 C 源代码中,包含该头文件并从 main 函数中需要它的位置调用该函数。将整个事情联系在一起,它应该可以工作。7) If I don't need to pass information of classes between the two programs, do I need to do anything about them?
不。只要您不包含来自 C 代码的任何 C++ 头文件(编译器无论如何都不会接受),C 代码甚至不知道类存在。所以,这里没有危险。
8) 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?)
当然,第一步是确保您可以分别编译两者。第二步是看是否可以用C++编译器(如上所述)编译C程序的主函数(仅主函数)。如果成功,开始将来自 C++ 主函数的元素合并到新的“合并”主函数中。如果不成功,请按照我刚才提到的步骤操作。
9) 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?
宏……这很难说。如果您按照创建可以从 C 主函数调用的 C++ 函数的过程进行操作,那么您基本上可以完美地隔离两个库,即它们被分别编译并在之后链接在一起。在这种情况下,MACRO 冲突不会有问题(但可能存在同名的函数,如果在 C++ 库中有些是
extern "C"
)。如果您尝试将主函数合并到一个 C++ 主函数中,您可能会遇到一些问题,即 C 头文件和 C++ 头文件之间的 MACRO 冲突,它们将被包含在一起。
关于c++ - 结合大型 C 和 C++ 程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17301704/