Проблеми с вграждането на Guile в C++

Аз съм програмист на Scheme и се опитвам да използвам Guile за извикване на функции на Scheme от C++ код в спецификация на Bison. Документацията относно Guile и C е страхотна; обаче не намерих много подходяща, актуална информация за Guile и C++. Тъй като технически всяка C програма е C++ програма, извикването на Scheme функции от C++ чрез Guile трябва да е достатъчно лесно. Уви, аз не съм C/C++ програмист, така че се надявах някои от C++ гурутата тук да могат да ми помогнат. Ето част от моя код:

%{
#include <fstream>
#include <iomanip>
#include <string>

using namespace std;

#include "List.h"

#include "paslex.h"
#include "paspar.h"
#include <libguile.h>

extern "C" {
#include "symtable.h"
 }

void yyerror(char* m);

extern ofstream tfs;
extern int line;
extern int col;

 extern "C" {
// Create namespace stack and lexical level 0 with built-in types.
   SCM namespace_stack;
   SCM namespace0;
   SCM real_type;
   SCM real_type_sym;
   SCM integer_type;
   SCM integer_type_sym;

   // errors begin here
   namespace_stack = make_name_stack();
   namespace0 = make_namespace();
   real_type = make_type_attr(64, 64);
   real_type_sym = make_type_sym("real", real_type);
   integer_type = make_type_attr(32, 32);
   integer_type_sym = make_type_sym("integer", integer_type);

   insert_symbol(real_type_sym, namespace0);
   insert_symbol(integer_type_sym, namespace0);
   push(namespace0, namespace_stack);
 }

%}

Моите функции за обвивка за кода на схемата са в symtable.c. Използването на същите тези функции от чист C работи добре. Извикването им от C++ генерира следната грешка на компилатора:

paspar.y:33: грешка: очакван конструктор, деструктор или преобразуване на тип преди токена „=“

...и подобна грешка за редове от 34 до 42. Използвам GCC 4.4.5 и Guile 1.6.8 на Ubuntu 10.10. Опитах се да преместя libguile.h include вътре и извън външния "C" блок, но резултатът е същият. Сигурен съм, че това е грешка за начинаещи, но помощта за този проблем ще бъде много оценена. Уведомете ме, ако е необходима повече информация. Включих symtable.h по-долу:

// Description: API to translator symbol table, including namespaces,
//              namespace stacks, and descriptors. 

// Constants used by descriptors.
#define CONSTANT_ID 0
#define FUNCTION_ID 1
#define PROCEDURE_ID 2
#define VARIABLE_ID 3
#define TYPE_SYM_ID 4
#define TYPE_ATTR_ID 5
#define TYPE_ENUM_ID 6
#define TYPE_RANGE_ID 7
#define TYPE_ARRAY_ID 8
#define TYPE_RECORD_ID 9
#define TYPE_POINTER_ID 10
#define TYPE_SET_ID 11


//------------------------------------NAMESPACE STACK--------------------------------------

SCM make_name_stack(); 
  // Create and return a namespace stack.

void push(SCM namspace, SCM stack);
  // Places a namespace on the stack.
  // @param stack The stack to place value on.
  // @param namspace The namespace to place on the stack.
  // @return None

SCM pop(SCM stack);
  // Returns namespace on top of stack.
  // @param stack The stack to return value from.
  // @return The namespace on top of stack.

void sremove(SCM stack);
  // Removes the top value on stack.
  // @param stack The stack to remove top value from.
  // @return None

int empty(SCM stack);
  // A predicate for determining if a stack is empty.
  // @param Stack The stack to test.
  // @return 1 if the stack is empty, 0 if it is not.

SCM find_stack_symbol(char* name, SCM stack);
  // Finds the symbol descriptor for the given identifier.
  // @param name The symbol name.
  // @param stack The stack to search.
  // @return The symbol descriptor or 0 if the symbol could not be found.

int lexical_level(char* name, SCM stack);
  // Find the lexical level of the identifier.
  // @param name The symbol name.
  // @param stack The stack to search.
  // @return The lexical level or -1 if the symbol could not be found.

int current_level(SCM stack);
  // Find lexical level of the top namespace.
  // @param stack The stack to search.
  // @return The lexical level or -1 if stack is empty.


//------------------------------------NAMESPACE--------------------------------------

SCM make_namespace();
  // Create and return a namespace.

void insert_symbol(SCM symbol, SCM namspace);
  // Insert descriptor into namespace
  // @param descriptor The descriptor to insert.
  // @param namspace The namespace to insert the descriptor into.
  // @return Nothing.

SCM find_symbol(SCM symbol, SCM namspace);
  // Search for symbol in target namespace.
  // @param symbol The symbol to search for.
  // @param namspace The namespace to search for symbol.
  // @return A symbol descriptor, or 0 if symbol not found.

int get_lex(SCM namspace);
  // Get lexical level of target namespace.
  // @param namspace The namespace whose lexical level to get.
  // @return Lexical level, or -1 if namespace has not yet been assigned one.


// ------------------------------SYMBOL DESCRIPTORS-------------------------------

SCM make_constant(char* name, SCM type, char* value);
  // Makes a constant symbol descriptor.
  // @param identifier Name of the constant.
  // @param type The constant's type descriptor.
  // @param value String representation of the constant.
  // @return A constant symbol descriptor.

SCM make_var(char* name, SCM type, double address);
  // Makes a variable symbol descriptor.
  // @param identifier Name of the variable.
  // @param type Address of the variable's type descriptor.
  // @param address Starting address of the variable itself.
  // @return A variable symbol descriptor.

SCM make_function(char* name, SCM params, double address);
  // Makes a function symbol descriptor.
  // @param identifier Name of the function.
  // @param params A list of function parameters. The first element should
  //               always be the return type.
  // @param address Address of the first function instruction.
  // @return A function symbol descriptor.

SCM make_procedure(char* name, SCM params, double address);
  // Makes a procedure symbol descriptor.
  // @param identifier Name of the procedure.
  // @param params A list of procedure parameters. Does not include a return type.
  // @param address Address of the first procedure instruction.
  // @return A procedure symbol descriptor.

SCM make_type_sym(char* name, SCM type);
  // Make a type symbol descriptor.
  // @param identifer Name of the type.
  // @param type Address of the type's attributes.
  // @return A type symbol descriptor.

int get_id(SCM descriptor);
  // Return descriptor id.

void get_name(SCM descriptor, char* name);
  // Return descriptor name.
  // @param descriptor Target descriptor.
  // @param name Output parameter for descriptor name.

int get_value(SCM descriptor, char* value);
  // Get string representation of a constant symbol descriptor.
  // @param descriptor Target descriptor.
  // @param value Output parameter for descriptor value.
  // @return 0 if not a constant, 1 if a constant.

double get_address(SCM descriptor);
  // Get address of descriptor.
  // @param descriptor Target descriptor.
  // @return address, or -1 if descriptor does not possess an address.

SCM get_params(SCM descriptor);
  // Get parameter list of descriptor.
  // @param descriptor Target descriptor.
  // @return parameter list, or 0 if descriptor does not possess a parameter list.

SCM get_type(SCM descriptor);
  // Get type referenced by descriptor.
  // @param descriptor Target descriptor.
  // @return type, or 0 if descriptor does not reference a type.

int set_type(SCM descriptor, SCM type);
  // Set type referenced by descriptor.
  // @param descriptor Target descriptor.
  // @param type Target type.
  // @return 1 if type set successfully, or 0 if it failed.


// -------------------------------TYPE DESCRIPTORS-------------------------------

SCM make_type_attr(double size, int align);
  // Make a type symbol attribute descriptor.
  // @param size Size of the type in bits.
  // @param align Type alignment in bits.
  // @return A type attribute descriptor.

SCM make_type_enum(double size, int align, SCM syms);
  // Make an enumerated type descriptor.
  // @param size Size of the type in bits.
  // @param align Alignment of the type in bits.
  // @param syms A Scheme list of symbol type descriptors.
  // @return An enumerated type descriptor.

SCM make_type_range(double size, int align, SCM low, SCM high);
  // Make a ranged type.
  // @param size Size of the type in bits.
  // @param align Alignment of the type in bits.
  // @param low Low value in the range (a symbol descriptor).
  // @param high High value in the range (a symbol descriptor).
  // @return A ranged type descriptor.

SCM make_type_array(double size, int align, SCM index, SCM element);
  // Make an array type.
  // @param size Size of the type in bits.
  // @param align Alignment of the type in bits.
  // @param index The type of allowable index values (a symbol descriptor).
  // @param element The type of allowable element values (a symbol descriptor).
  // @return An array type descriptor.

SCM make_type_record(double size, int align, SCM vars);
  // Make a record type.
  // @param size Size of the type in bits.
  // @param align Alignment of the type in bits.
  // @param vars A Scheme list of variable type descriptors.
  // @return A record type descriptor.

SCM make_type_pointer(double size, int align, SCM type);
  // Make a pointer type.
  // @param size Size of the type in bits.
  // @param align Alignment of the type in bits.
  // @param type The type pointer is referencing.
  // @return A pointer type.

SCM make_type_set(double size, int align, SCM enum_type);
  // Make a set type.
  // @param size Size of the type in bits.
  // @param align Alignment of the type in bits.
  // @param enum The enumerated type used by this set.
  // @return A set type.

SCM make_type_null();
  // Make a null type for use when the descriptor type is not known
  // at creation time.

int check_null(SCM type);
  // Checks if a type is null.
  // Returns 1 if null, or 0 if not null.

double get_size(SCM descriptor);
  // Return size of type in bits.

int get_align(SCM descriptor);
  // Return alignment of type in bits.

SCM get_vars(SCM descriptor, int* boolean);
  // Return variable list from record descriptor.
  // @param descriptor Target descriptor.
  // @param boolean Output parameter returns 0 if not record descriptor.
  // @return A variable list.

SCM get_index(SCM descriptor, int* boolean);
  // Return index type from array descriptor.
  // @param descriptor Target descriptor.
  // @param boolean Output parameter returns 0 if not array descriptor.
  // @return Index type.

SCM get_element(SCM descriptor, int* boolean);
  // Return element type from array descriptor.
  // @param descriptor Target descriptor.
  // @param boolean Output parameter returns 0 if not array descriptor.
  // @return Element type.

SCM get_low(SCM descriptor, int* boolean);
  // Return low type from range descriptor.
  // @param descriptor Target descriptor.
  // @param boolean Output parameter returns 0 if not range descriptor.
  // @return Low type.

SCM get_high(SCM descriptor, int* boolean);
  // Return high type from range descriptor.
  // @param descriptor Target descriptor.
  // @param boolean Output parameter returns 0 if not range descriptor.
  // @return High type.

SCM get_syms(SCM descriptor, int* boolean);
  // Return symbol list from enumerated descriptor.
  // @param descriptor Target descriptor.
  // @param boolean Output parameter returns 0 if not enumerated descriptor.
  // @return Symbol list.

person Jerrad Genson    schedule 21.02.2011    source източник
comment
само няколко неща: без никакви номера на редове, не мога да разбера кой ред, който сте публикували, е ред 41 - може да си струва да поставите коментар като грешка тук на въпросния ред. Освен това се надявам тези знаци за процент да не са в действителния ви код :) О, и за протокола, C++ не е истинска надмножество на C, така че има някои C програми, които не са валидни C++ програми (въпреки че разликите обикновено са доста малки).   -  person Mac    schedule 21.02.2011
comment
Свършен. Благодаря ви за обратната връзка. Между другото, знаците за процент са част от спецификацията на Yacc.   -  person Jerrad Genson    schedule 21.02.2011


Отговори (1)


Опитвате се да извършвате работа извън функция, което не е разрешено в C и само с големи ограничения в C++. Твърденията, започващи с

namespace_stack = make_name_stack();

не трябва да е на най-високо ниво, а вътре във функция (напр. main). Защо използвате блок extern "C" между другото?

person Fred Foo    schedule 22.02.2011