Mail Archives: djgpp/2001/01/12/06:36:42
From: | "Tim Van Holder" <tim DOT vanholder AT falconsoft DOT be>
|
Subject: | Re: Calling C++ functions from C (or using Bison with C++)
|
Newsgroups: | comp.os.msdos.djgpp
|
Organization: | Falcon Software NV
|
Message-ID: | <20010112.122527.2027907669.15238@falconsoft.be>
|
User-Agent: | Pan/0.9.2 (Unix)
|
X-No-Productlinks: | Yes
|
Lines: | 174
|
Date: | Fri, 12 Jan 2001 11:26:07 GMT
|
NNTP-Posting-Host: | 195.207.71.6
|
X-Complaints-To: | abuse AT Belgium DOT EU DOT net
|
X-Trace: | nreader1.kpnqwest.net 979298767 195.207.71.6 (Fri, 12 Jan 2001 12:26:07 MET)
|
NNTP-Posting-Date: | Fri, 12 Jan 2001 12:26:07 MET
|
To: | djgpp AT delorie DOT com
|
DJ-Gateway: | from newsgroup comp.os.msdos.djgpp
|
Reply-To: | djgpp AT delorie DOT com
|
In a burst of inspiration, "Nimrod A. Abing"
<n_abing AT ns DOT roxas-online DOT net DOT ph> wrote this on
<3 DOT 0 DOT 1 DOT 32 DOT 20010112084816 DOT 006bc314 AT wingate>:
> parser. I intended to call C++ functions from within the parser
> rule-actions until I realized that this would be a problem because the
> parser is in C.
If it just regular functions you're calling, and not class members, it
should suffice to use 'extern "C"' in front of the prototypes of those
functions. This also makes it impossible to overload those functions
though.
===
[test.h]
extern "C" void* MyCPlusPlusFunc(int x);
[test.cc]
extern "C"
void*
MyCPlusPlusFunc(int x)
{
void* ret = 0;
try {
ret = reinterpret_cast<void*>(new MyFooStructure);
}
catch(...) {
return 0;
}
}
[foo.y]
%{
#include "test.h"
%}
...
rule: element-1 element-2 { $$ = MyCplusPlusFunc(); } ;
===
Alternatively, you could create a C wrapper for each C++ function you
use.
This has the advantage that you can use overloaded C++ functions (you
just need to make the names of the wrappers different). And if you don't
mind screwing with casts, you could even use class members, although I
certainly don't recommend it (and I'm not even sure the compiler will
allow you to do such evil casts (might need to use C-style casts instead
of reinterpret_cast)).
===
[test.h]
class MyFoo {
public:
MyFoo() {}
~MyFoo() {}
void member(void);
};
unsigned long
MyIntegralFunc(unsigned long)
{
...
}
unsigned int
MyIntegralFunc(unsigned int)
{
...
}
unsigned short
MyIntegralFunc(unsigned short)
{
...
}
[testwrap.h]
#ifdef __cplusplus
extern "C" {
#endif
void* new_myfoo(void);
void myfoo_member(void*);
void delete_myfoo(void*);
unsigned long mylongfunc(unsigned long);
unsigned int myintfunc(unsigned int);
unsigned short myshortfunc(unsigned short);
#ifdef __cplusplus
}
#endif
[testwrap.cc]
#include <new>
#include "test.h"
#include "testwrap.h"
unsigned long
mylongfunc(unsigned long ul)
{
return MyIntegralFunc(ul);
}
unsigned int
myintfunc(unsigned int ui)
{
return MyIntegralFunc(ui);
}
unsigned short
myshortfunc(unsigned short us)
{
return MyIntegralFunc(us);
}
// Here there be dragons
void*
new_myfoo(void)
{
MyFoo* m = new (nothrow) MyFoo;
return reinterpret_cast<void*>(m);
}
void
myfoo_member(void)
{
MyFoo* object = reinterpret_cast<MyFoo*>(m);
object->member();
}
void
delete_myfoo(void* m)
{
MyFoo* object = reinterpret_cast<MyFoo*>(m);
delete object;
}
[foo.y]
%{
#include "test.h"
%}
...
sub-rule: element-1 element-2 { $$ = new_myfoo(); mylongfunc(666); } ;
foo: sub-rule
{
myshortfunc(7);
myfoo_member($1);
delete_myfoo($1);
myintfunc(13);
}
===
A final alternative would be to edit bison.simple/bison.hairy to be a
valid C++ source file. Then you can simply run bison to generate the
code, and use gcc (-x c++) to compile it as C++. You could even try
turning the skeletons into an implementation of some class (and create a
generic header (like FlexLexer.h) for applications to use).
--
Tim Van Holder - Falcon Software N.V.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
This message was posted using plain text. I do not endorse any
products or services that may be hyperlinked to this message.
- Raw text -