Diogo Ferreira
Diogo Ferreira

Reputation: 25

C overriding C++ method

expr.hpp

typedef int (*evaluate)(PExp);
typedef void (*printTo)(PExp, FILE *);
typedef void (*Exp_free)(PExp);

class Expression {
public:
     virtual int  evaluate()          abstract; 
     virtual void printTo(FILE * out) abstract;  
     virtual void free();                       
};

class Value : public Expression {
protected:
    int value;
    Value(int value);
public:
    int evaluate();
};

Expression.h

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

typedef struct expression Expression;
typedef Expression * PExp;

typedef int (*evaluate)(PExp);
typedef void (*printTo)(PExp, FILE *);
typedef void (*Exp_free)(PExp);

typedef struct {
    evaluate exp_evaluate;
    printTo exp_printTo;
    Exp_free exp_free;
} vTable;

struct expression {
    vTable * v;
};

void expression_init(PExp this);
void exp_free(PExp this);

Value.h

#include "Expression.h"

typedef struct {
    Expression super;
    int value;
} Value;

void value_init(Value * this, int value);
int value_evaluate(Value * this);

Constant.h

typedef struct {
    Value super;
} Constant;

void constant_init(Constant * this, int value);
void constant_free(Constant * this);
void constant_printTo(Constant * this, FILE * out);

expr.h

#include "Expression.h"
#include "Value.h"
#include "Constant.h"

main.c

#include "expr.h"

void constant_init(Constant * this, int value) {
    _ZN5ValueC2Ei((Value *)this, value);
    printf("%d\n", this->super.super.v->exp_evaluate((PExp)this));
    this->super.super.v->exp_printTo = (printTo)constant_printTo; // MARK
}

void constant_printTo(Constant * this, FILE * out) {
    fprintf(out, "%d", this->super.value );
    putchar('\n');
}

I'm currently trying to implement some code which constructs some objects in C while using C++ at the same time. The classes "Expression" and "Value" are given in C++ and I have to implement the class "Constant" which extends "Value" in C. I cannot change anything in the C++ files (including new files) so that's why I call the "Value" constructor by it's mangled name. The question is: I can call the method exp_evaluate which is defined in the class "Value" but when I try to override the method exp_printTo (MARKED line) it always gives me Segmentation Fault, so what am I doing wrong here?. If I try to call the method, instead of trying to assign another value to the function pointer, it terminates as expected because it is a pure virtual method. Here is the makefile showing that "main" is compiled with 3 C++ files and main.c:

main: use-expr.o expr.o main.o
    g++ -o use-expr-c use-expr.o expr.o main.o -g

use-expr.o: use-expr.cpp expr.hpp
    g++ -Wall -pedantic -g -c use-expr.cpp -g

expr.o: expr.cpp expr.hpp
    g++ -Wall -pedantic -g -c expr.cpp -g

main.o: main.c
    gcc -Wall -pedantic -std=c99 -g -c -o main.o main.c -g

It all compiles, the only error I get is at runtime. I hope there's enough information. Thank you in advance.

Upvotes: 0

Views: 136

Answers (1)

abligh
abligh

Reputation: 25129

I'd suggest you implement a small wrapper (in C++) that calls the C++, and make the function there have C linkage using extern C. This is a far more reliable method than calling mangled C++ names.

If you really want to know what's up, I'm afraid it's time to break out gdb.

Upvotes: 3

Related Questions