0

我将一些用 C++ 编写的代码混合到用 C 编写的代码(由 lex/yacc 生成)。

我有一个指针(指向 C++ 类的 void 指针),它在(由 yacc 生成的解析函数)的main内部和内部可见。parser()该指针位于解析器的 .h 中,如下所示。

我希望所指向的对象con具有全局范围,实际上,它具有全局范围的指针,我可以像在解析器函数中一样访问 main 中的类,但里面的对象不能。我的意思是,我可以在解析器中工作并向其添加数据,但是当它返回到 main 时,它是空的,不是销毁而是空的。看起来 parse 中的对象与 main 中的对象不同。

我想在整个项目中只有一个对象。我该怎么做?

注意:我只想保留一个对象,所以我不想讨论复制构造函数(它可以工作并且已经过测试),我只是一个对象(类似于单例)。

================================== main.cpp ============== ===========================

#include <stdio.h>
#include <stdlib.h>
#include "Context.h"
extern "C" {
    #include "parser.h"

}
int main(int argc, char** argv) {
    *stderr = *stdout;
    con = new_Context();
    yyin=fopen(argv[1],"rb");
         ret = yyparse();
    return  ret;
}

================================= parser.h =============== ============================

#ifndef PARSER
#define PARSER

#include <stdio.h>
#include <stdlib.h>
#include "C_Context.h"



// ================ updated ========================
 #define LINKAGE extern
#ifdef __cplusplus
extern "C" {

#endif
LINKAGE C_Context *con;
#ifdef __cplusplus
}
#endif    
// ================ updated ========================



extern FILE* yyin;

int yyparse();

#endif

====================================== parser.c ========== ==============================

// ================ updated ========================
#include "parser.h"
#ifdef __cplusplus
extern "C" {
#endif
C_Context *con;
#ifdef __cplusplus
}
#endif



// ================ updated ========================

#include "y.tab.c"

=================================== C_Context.h (fragmrnt) ========== ==============

typedef void C_Context;
typedef void C_TypeGroup;



#ifdef __cplusplus
extern "C" {

#endif

    // create a context and return the class as void pointer
    C_Context * new_Context();

#ifdef __cplusplus
}
#endif

==================================== C_Context.cpp(片段)========= ======

#include "Context.h"
#include <iostream>
#define con (*((Context *)c_con))

using namespace std;
extern "C" {

    C_Context * new_Context(){
        C_Context* ret =0x0;
        try{
            ret = (C_Context*)  new Context();
        }catch(char * ex){
            cerr<< "Runtime error:" << ex; 
        }
        return ret;
    }
}

更新:

我更新了您发疯的建议,但仍然无效。完全相同的问题。我做错了什么?

更新 2:

有人建议我更多地描述这个问题。我不确定我应该描述什么,但我会尝试。

我有一个类名上下文,其中包含所有对象和实现解释所需的函数。该对象是具有地图/矢量类的地图/矢量的复杂动画。解析一切顺利,我的意思是,我可以通过它的包装器 C_Context 访问上下文类的所有功能。我的问题是该语言应该首先解析一个初始化文件然后是脚本,因为对象必须在第一个初始化文件之后与数据保持一致才能正确运行脚本。

当然还有其他方法,我可以制作一个包含所有脚本和初始化文件的临时文件。但是这个限制还是很难将某种包含在语言里面的可能性。如果我这样做,那么我必须首先读取包含文件的文件并将所有文件添加到一个文件中,最后运行真正的解释。因此,如果可能的话,我更喜欢能够多次运行解析器。为此,我需要上下文保持不变。

我不知道这是否有帮助,但很好。

更新 3

我应用了建议,据我所知,仍然是同样的事情。在 parser() 内部的指针上添加元素,我可以使用它。但是当我回到 main 时又是空的(没有破坏)。

(我检查了一下语法和正字法)

4

2 回答 2

5

在标头中声明变量extern并在 .c 文件中定义它。否则每个翻译单元都有自己的定义。

更新:

看到您已经更新了代码,parser.c 应该如下所示(以防编译器将 .c 文件编译为 C++):

// ================ updated ========================
#ifdef __cplusplus
extern "C" {
#endif
C_Context *con;
#ifdef __cplusplus
}
#endif


// ================ updated ========================

#include "y.tab.c"

你现在也可以删除extern "C" { ...#include "parser.h"

于 2013-05-08T07:35:19.753 回答
0

在这样的标题中:

#ifndef myinclude_h
#define myinclude_h

#ifdef MAIN
int x;
#else
extern int x;
#endif

#endif

在这种情况下,您必须确保在编译过程中的某个地方 MAIN 被定义在一个文件中。

或者如上所述的其他方式:

。H:

#ifndef myinclude_h
#define myinclude_h

extern int x;

#endif

.cpp:

int x;

详细说明:

如果你想要一个全局变量,你可以在一些头文件中删除它,如上所示的 extern。这只是一个声明,它告诉编译器“某处”有一个名为 x 的 int 类型变量。在您的 c 或 cpp 文件之一中,您实际上在全局空间中声明了变量。意思是,不是在一个类或什么里面,而是在所有函数之外。例如,在 main 的顶部,您可以在 main 出现之前编写它:

int x;
main()
{
}

无论您想在何处使用此变量,都必须包含 extern 声明所在的头文件,然后您就可以访问它,就像任何其他变量一样。

在其他文件中:

#include "myinclude.h"

void fkt()
{
   if(x < 10)
       x+= 10;
   cout << x << endl;
}

更新

在你的主要:

 #include <stdio.h>
 #include <stdlib.h>
 #include "Context.h"

 #include "parser.h"

 int main(int argc, char** argv) {
     *stderr = *stdout;
     con = new_Context();
     yyin=fopen(argv[1],"rb");
     ret = yyparse();
     return  ret;
 }

在你的 parser.c

 #ifdef __cplusplus
 extern "C" {
 #endif

 C_Context *con;

 #ifdef __cplusplus
 }
 #endif

那应该这样做。

无论您的 new_context() 在哪里:

 #include "parser.h"
于 2013-05-08T07:39:59.460 回答