Wrapping C/C++ Problem

Building a wrapper constructor for a C++ class in a C header.

Page 1 of 1

11 Replies - 1789 Views - Last Post: 29 April 2010 - 12:56 PM Rate Topic: -----

#1 ashapi  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 27-April 10

Wrapping C/C++ Problem

Posted 27 April 2010 - 05:48 PM

Hi,

I have a question regarding wrapping/linking protocols between C and C++. I'm working on existing C++ code that I have to wrap into a C object file for use in a different environment, namely I have a main C program that has to be able to link to the C++ generated .o effectively. Also, I have a C header file that specifies the interface struct between the old environment and the new one that my C main() will have to utilize. I've created a .cc, which will generate the .o, that includes other required C++ headers and the C header interface, specifying C linkage for the interface.h with 'extern "C"'.

In order to do this I created wrapper functions to virtual C++ member functions (in other .hh's) by passing void* as a parameter to the wrapper, dereferencing the pointer and calling the member function within the wrapper, and then specifying C linkage as above. I need to create a 'constructor' wrapper function (in my interface.h) that returns a void* to a C++ class instance. With this I can instantiate and then dereference the pointer in my C main, allowing access to C++ class instances; however, because I can't include C++ headers in the interface.h, I can't find a way to declare the instance of a specific C++ class type. Likewise I need to build a 'destructor' wrapper function which will deallocate the instance of this class but I run into the same problem.

My other question is that the existing code has an analogous C++ struct with exactly the same members as the interface.h struct, although it is given in a C++ header. The other .hh's require this C++ type to be passed as function parameters. The only idea I had would be to use static_cast or reinterpret_cast<c++_type>c_type in functions that require the C++ type as a parameter. I am not familiar with the implementation details of these casts and don't know if it will work, granted I can't debug this without the other fix. Is there another implementation I am not thinking of?

Any help would be greatly appreciated. This is my first post so please don't rip me apart if I messed up some posting conventions, but a sincere correction would not go unheard.

Thanks in advance,

Andrew

Is This A Good Question/Topic? 0
  • +

Replies To: Wrapping C/C++ Problem

#2 Oler1s  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1395
  • View blog
  • Posts: 3,884
  • Joined: 04-June 09

Re: Wrapping C/C++ Problem

Posted 27 April 2010 - 06:51 PM

Quote

however, because I can't include C++ headers in the interface.h, I can't find a way to declare the instance of a specific C++ class type.
I'm confused here. Your interfaces should not refer to any C++ only types. The whole point of the interface is that it's C friendly. Your implementations should have C linkage, but be compiled as C++. Your interface (the header file with the declarations) just has the function signatures, and the signatures are all C friendly. Why would your interface functions depend on declarations in the C++ headers?

On your second question, I have to think about your context and problem a bit more before I can really speak with clarity. That said, casting is required, if you pass a pointer of one type and need it to be treated as another. The question is what kind.

If someone else has more time to reflect on your second question, hopefully they can help you on the second point. But I am truly confused on the first. Your C header of declarations should not need to reference the C++ headers.

EDIT: Although, I should note if you expect that your analagous C struct can be directly treated as it's representative C++ type, you're playing with fire. The C struct does not live in the inheritance hierarchy, and whether or not it can be directly interpreted as the C++ type is an implementation detail. Again, I have to think about this a bit more, but the warning stands...

This post has been edited by Oler1s: 27 April 2010 - 06:54 PM

Was This Post Helpful? 0
  • +
  • -

#3 ashapi  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 27-April 10

Re: Wrapping C/C++ Problem

Posted 27 April 2010 - 07:53 PM

View PostOler1s, on 27 April 2010 - 05:51 PM, said:

I'm confused here. Your interfaces should not refer to any C++ only types. The whole point of the interface is that it's C friendly. Your implementations should have C linkage, but be compiled as C++. Your interface (the header file with the declarations) just has the function signatures, and the signatures are all C friendly. Why would your interface functions depend on declarations in the C++ headers?

This might clear some of the confusion up. Below was the interface header provided to me, which contains the three nonmember functions to be defined within the header itself. The comments above the function COOC_start refer to a "coordination controller" that is an abstract base class defined in a C++ header.

#ifndef _COORCTRL_H
#define _COORCTRL_H

/** coorctrl.h
    
    Interface specification for coordination controllers.

*/

#define COOC_LEG_SPACE_DIM 6

/** State mailbox structure
  Contains all fields for exchanging state with controller
  Fields are ordered to allow tight struct field alignments
*/

struct COOC_State {
    //! Leg positions
    double position [COOC_LEG_SPACE_DIM];
    //! Leg velocities
    double speed [COOC_LEG_SPACE_DIM] ;
    //! Torques
    double torque [COOC_LEG_SPACE_DIM];
    //! Current time
    double t;
    //! Turning offset
    double skew;
    //! Forward run speed
    double forward;
    //! Touchdown indicator (as char, to use with C code)
    double contact [COOC_LEG_SPACE_DIM];
};

/** Initialize a coordination controller (constructor)
    Returns a handle to the controller object or NULL on error
**/
extern void *COOC_start( void ){

};


/** Close down and deallocate a coordination controller (destructor) */
extern void COOC_stop(void* cooc){

};


/** Workfunction of a coordination controller
    INPUT:
       cooc -- coordination controller handle returned by COOC_start 
       st -- state information to use for the update
    OUTPUT:
       changes to st->torque
    
    THEORY OF OPERATION:
       *st is used to exchange information between the robot and its
       controller. 
       Leg positions and speeds are in st->position, st->speed
       Legs that have triggered a touchdown indication have a non-zero
       value in their st->contact entry.
       The joystick controller state is expressed as a number in the
       range -1..1 in speed (for front-back) and -1..1 in skew 
       (for left-right).
       The number of seconds elapsed since calling COOC_start is in
       the field st->t; precision should be at least down to the mSec,
       and time should be non-decreasing in consecutive calls.
       
       After returning, the fields st->torque contain the desired 
       torques for the various legs.
**/             
extern void COOC_runOnce( void *cooc, struct COOC_State *st );


#endif /* _COORCTRL_H */




Quote

On your second question, I have to think about your context and problem a bit more before I can really speak with clarity. That said, casting is required, if you pass a pointer of one type and need it to be treated as another. The question is what kind.

If someone else has more time to reflect on your second question, hopefully they can help you on the second point. But I am truly confused on the first. Your C header of declarations should not need to reference the C++ headers.

EDIT: Although, I should note if you expect that your analagous C struct can be directly treated as it's representative C++ type, you're playing with fire. The C struct does not live in the inheritance hierarchy, and whether or not it can be directly interpreted as the C++ type is an implementation detail. Again, I have to think about this a bit more, but the warning stands...


The interface is the COOC_State struct instance to be declared in the main C program. This is supposed to communicate with the C++ class instances and their member functions via casting, as you suggested, to the C++ analogous struct. If the C++ struct is exactly like same in every aspect as the C struct (quoting the comment: "Fields are ordered to allow tight struct field alignments") then should I still be careful about playing with fire? I didn't mean to imply an inheritance relationship between the two structs....more of an exact word-for-word copy. With your casting suggestion considered, could something like the following work if it were placed inside a wrapper function for a virtual member "foo" of another C++ class?


extern "C" void foo(COOC_State* cooc){ //wrapper function for foo, which is defined as a virtual member function for another C++ class
	reinterpret_cast<c++_struct_name*>cooc;
	cooc->foo();
}




Thanks for your help so far.
Was This Post Helpful? 0
  • +
  • -

#4 Oler1s  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1395
  • View blog
  • Posts: 3,884
  • Joined: 04-June 09

Re: Wrapping C/C++ Problem

Posted 27 April 2010 - 08:18 PM

Yeah, there's a problem in the code.

extern void *COOC_start( void ){

};



So what extern says is that you are providing a declaration only. It's basically redundant for functions, because you imply a declaration by leaving out the definition. (Not so for variables). What's problematic here is that you indicate that you are declaring COOC_start, and then provide a function body (the braces indicate a function body). So you syntactically state you provide a declaration, while syntactically providing a definition....

All you need in the file is void *COOC_start( void ); Extern is redundant and there should be no function body. The definition is provided in the C++ file (and thus you also need to mark the definition with extern "C").

Quote

If the C++ struct is exactly like same in every aspect as the C struct (quoting the comment: "Fields are ordered to allow tight struct field alignments") then should I still be careful about playing with fire?
This shouldn't be a problem then. C++ considers classes and structs the same, so if you have a struct that is a replica of a class with POD types, you've basically got the same thing. I need to confirm this to make sure you aren't tripping on something obscure, but it feels right in my mind. Then again, this is C++.

Your code is almost right.

extern "C" void foo(COOC_State* cooc){ //wrapper function for foo, which is defined as a virtual member function for another C++ class
        c++_struct_name *cpp_struct = reinterpret_cast<c++_struct_name*>cooc;
        cpp_struct->foo();
}



Casting forms an expression. Still have to assign it somewhere.
Was This Post Helpful? 0
  • +
  • -

#5 ashapi  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 27-April 10

Re: Wrapping C/C++ Problem

Posted 27 April 2010 - 08:46 PM

Quote

So what extern says is that you are providing a declaration only. It's basically redundant for functions, because you imply a declaration by leaving out the definition. (Not so for variables). What's problematic here is that you indicate that you are declaring COOC_start, and then provide a function body (the braces indicate a function body). So you syntactically state you provide a declaration, while syntactically providing a definition....


Ah I'm retarded...I modified the original copy of the header file I was given to include the function body brackets and then assumed later (when I forgot I did this) that the function had to be defined in the header itself. Thanks so much for pointing this out...re-downloading the original header from the code repository shows that it didn't have the brackets.

Quote

Casting forms an expression. Still have to assign it somewhere.


Thanks for that too. I really appreciate your help!
Was This Post Helpful? 0
  • +
  • -

#6 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5775
  • View blog
  • Posts: 12,587
  • Joined: 16-October 07

Re: Wrapping C/C++ Problem

Posted 28 April 2010 - 06:14 AM

I never tried going from C++ to C before. It sounded like fun.

Note you do NOT need a void pointer. You can fake C out with a struct. Which makes sense. The C implementation is a pretty close to how C++ handles things under the covers, transparently passing an instance around to associated methods.

Here's my attempt.

CppCode.h
#ifndef CPP_CODE_H
#define CPP_CODE_H


class Circle {
private:
	const double radius;

public:
	Circle();
	Circle(double r);
	double getRadius();
	double getDiameter();
	double getCircumference();
	double getArea();
	void print();
};

#endif



CppCode.cc
#include <iostream>
#include "CppCode.h"

using namespace std;

const double PI = 3.14159;

Circle::Circle() : radius(1) {}
Circle::Circle(double r) : radius((r<=0)?1:r) { }
double Circle::getRadius(){ return radius; }
double Circle::getDiameter(){ return radius + radius;}
double Circle::getCircumference(){	return getDiameter() * PI;}
double Circle::getArea(){ return radius * radius * PI;}

void Circle::print(){
	cout << "Circle:" << endl;
	cout << "Radius        = " << getRadius() << endl;
	cout << "Diameter      = " << getDiameter() << endl;
	cout << "Circumference = " << getCircumference() << endl;
	cout << "Area          = " << getArea() << endl;
}




We use these long names to avoid name collisions.
CppCodeWrapper.h
#ifndef CPP_CODE_WRAPPER_H
#define CPP_CODE_WRAPPER_H

extern "C" {
Circle *circleCreate(double radius);
void circleFree(Circle *);
double circleGetRadius(Circle *);
double circleGetDiameter(Circle *);
double circleGetCircumference(Circle *);
double circleGetArea(Circle *);
void circlePrint(Circle *);
}

#endif




CppCodeWrapper.c
#include <cstdlib>

#include "CppCode.h"
#include "CppCodeWrapper.h"

Circle * circleCreate(double radius) { return new Circle(radius); }

void circleFree(Circle *obj) { delete obj; }
double circleGetRadius(Circle *obj) { return obj->getRadius(); }
double circleGetDiameter(Circle *obj) { return obj->getDiameter(); }
double circleGetCircumference(Circle *obj) { return  obj->getCircumference(); }
double circleGetArea(Circle *obj) { return obj->getArea(); }
void circlePrint(Circle *obj) { obj->print(); }



Because calling CppCodeWrapper.h directly doesn't work, it's still too C++y.
CppCodeCalls.h
#ifndef CPP_CODE_CALLS_H
#define CPP_CODE_CALLS_H

struct Circle;
typedef struct Circle Circle;

Circle *circleCreate(double radius);
void circleFree(Circle *);
double circleGetRadius(Circle *);
double circleGetDiameter(Circle *);
double circleGetCircumference(Circle *);
double circleGetArea(Circle *);
void circlePrint(Circle *);

#endif




The big payoff.
main.c
#include <stdlib.h>
#include <stdio.h>
#include "CppCodeCalls.h"

int main() {
	Circle *circle;
	circle = circleCreate(10);
	
	printf("Diameter = %f\n", circleGetDiameter(circle));
	circlePrint(circle);
	circleFree(circle);

	return 0;
}



Because more than a few files wants a Makefile
Makefile
CC := gcc
CXX := g++
CFLAGS := -Wall -g
LIBS := -lstdc++
EXEC := test

OBJS := main.o CppCode.o CppCodeWrapper.o

all: $(EXEC)

$(EXEC): $(OBJS)
	$(CC) $(CFLAGS) $(LIBS) -o $(EXEC) $(OBJS)

%.o : %.c
	$(CC) $(CFLAGS) -c $< -o $@

%.o : %.cc
	$(CXX) -c $< -o $@

clean:
	rm -f $(OBJS)




Hope this helps. I had fun.
Was This Post Helpful? 0
  • +
  • -

#7 ashapi  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 27-April 10

Re: Wrapping C/C++ Problem

Posted 29 April 2010 - 12:20 PM

So I've gotten my cpp wrapper to generate an object file but I keep getting undefined references to the functions I am calling in my main C program when I try to link.

Here is my cpp source wrapper (wrapper.cc) which includes the interface header coorctrl.h. The wrapper defines the functions prototyped in my interface header that are to be called in the main C (the error-causing ones).

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "DataExchanger.hh"
#include "MathOfRAM04.hh"
#include "RemoteDX.hh"
#include "MathOfRAM04Spec.hh"

class Wrap {
	public:
		//RAM04_Spec* cfg;//probably not necessary to put it in the class
		MathOfRAM04* ctrl;
		RemoteDX* rdx;
	};

/**__________________coordination controller wrapper functions___________________**/

#ifdef __cplusplus
	 extern "C" {
#endif 

#include "coorctrl.h"

/** Initialize a coordination controller (constructor)
    Returns a handle to the controller object or NULL on error
**/
extern void *COOC_start( void ){
	static Wrap* wrap = new Wrap;
	static MathOfRAM04* ctrl = wrap->ctrl;
	ctrl = new MathOfRAM04;
	static RemoteDX* rdx = wrap->rdx;
	rdx = new RemoteDX;
	double t0 = 0;
  	double dt = 0.1;
  	double mass = 1;
  	static CoorControllerState st = {0,}; //The struct contains doubles for: position, speed, torque, current time, turning offset, forward run speed, and touchdown indicator.
	static RAM04_Spec* cfg;

	cfg->set_qR1( 2.65,2.95 ); //Ranges around touchdown and liftoff where we are able to reduce the voltage passed to each motor at the appropriate times (eqn. 9)
	cfg->set_qR2( -3,-2.7 );
	cfg->sigma0= 66; //Saturation function - minimum voltage commanded to the motors
	cfg->sigmaM= 77; //Maximum voltage commanded to the motors
	cfg->beta1= 0.02; //0.1; //Not sure about hte betas
	cfg->beta2= 0;      
	cfg->Kd= 0.001; //0.002; //Gain, from eqns. 13 and 15
	cfg->u0= 0;    //From equation 15, not sure what this is
	cfg->omega= 2;  //Gait angular frequency
	cfg->Kfb= 0;  //gain
	cfg->Kcd= 0;  //gain
	cfg->Ktri= 0;  //gain
	cfg->Ktds= 0;  //gain
	cfg->td_Kp = 0;  //Touchdown sensing P gain
	cfg->td_Kd = 0;  //Touchdown sensing D gain 
	cfg->gDut = 0.4;  // Gait (Buehler clock) duty factor
	cfg->gSwp = 0.6;  // Gait (Buehler clock) Sweep
	cfg->gOfs = 0.0;  // Gait (Buehler clock) Offset
	cfg->turnOfs = -1;  //Turn offset
	cfg->turnPhase = 0;  //Phase for turn offset change
	cfg->fwdGain = 10;  // Forward command nonlinearity
	(wrap->ctrl)->set_cfg( cfg );



// 	Bind variables to be exposed to the RDX
	(wrap->rdx)->BIND1(dt);
	(wrap->rdx)->BIND1(mass);
	(wrap->rdx)->bind(&st.t,"st_t");
	(wrap->rdx)->bind(st.position,"st_q",LegSpaceDim);
	(wrap->rdx)->bind(st.speed,"st_dq",LegSpaceDim);
	(wrap->rdx)->bind(st.torque,"st_ddq",LegSpaceDim);
	(wrap->rdx)->bind(st.contact,"st_contact",LegSpaceDim);
	(wrap->rdx)->bind(&st.skew,"st_skew");
	(wrap->rdx)->bind(&st.forward,"st_forward");  
	(wrap->ctrl)->bindDX(wrap->rdx);
	
	
	return (void*)wrap;
};

/** Close down and deallocate a coordination controller (destructor) */
extern void COOC_stop(void *cooc){

	delete ((static_cast<Wrap*>(cooc))->ctrl);
	delete ((static_cast<Wrap*>(cooc))->rdx); 
	//delete ((static_cast<Wrap*>(cooc))->cfg); 
	delete (static_cast<Wrap*>(cooc));
	
};

/** Workfunction of a coordination controller
    INPUT:
       cooc -- coordination controller handle returned by COOC_start 
       st -- state information to use for the update
    OUTPUT:
       changes to st->torque
    
    THEORY OF OPERATION:
       *st is used to exchange information between the robot and its
       controller. 
       Leg positions and speeds are in st->position, st->speed
       Legs that have triggered a touchdown indication have a non-zero
       value in their st->contact entry.
       The joystick controller state is expressed as a number in the
       range -1..1 in speed (for front-back) and -1..1 in skew 
       (for left-right).
       The number of seconds elapsed since calling COOC_start is in
       the field st->t; precision should be at least down to the mSec,
       and time should be non-decreasing in consecutive calls.
       
       After returning, the fields st->torque contain the desired 
       torques for the various legs.
**/             
extern void COOC_runOnce( void *cooc, struct COOC_State *_st ){
	Wrap* wrap = static_cast<Wrap*>(cooc);
	void* st=(void*)_st; //maybe? otherwise I get invalid static_cast, alternative would be reinterpret_cast
	//int st = _st; //maybe also?

	(wrap->ctrl)->process(static_cast<CoorControllerState*>(st));

	for (int i=0; i<50; i++) 
      		(wrap->rdx)->runOnce(); //run RDX
};

#ifdef __cplusplus
};
#endif 





Here is the main C program: cct3.c

#include "coorctrl.h"

int main(int argc, char *argv[]){
	
	static struct COOC_State st = {0,};
	void* controller_wrap = COOC_start();
	COOC_runOnce(controller_wrap, &st);
	COOC_stop(controller_wrap);
	
	return(0);
	
}; 



The undefined references are from COOC_start(), COOC_runOnce(), and COOC_stop().

Among many others, I've been using the compile line:

g++ -g wrapper.cc cct3.c -lm -o cct3

Any help would be appreciated.

Thanks,

Andrew
Was This Post Helpful? 0
  • +
  • -

#8 Oler1s  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1395
  • View blog
  • Posts: 3,884
  • Joined: 04-June 09

Re: Wrapping C/C++ Problem

Posted 29 April 2010 - 12:28 PM

Please copy-paste error messages. Don't describe their existence. It may be undecipherable gibberish to you, but we can actually read them, gather information, and use that information for a diagnosis.

If you want help, don't sabotage your request by omitting information.

EDIT:

Read your the signatures of function definitions carefully. You wrote extern ..... when it should be extern "C" ....

EDIT2 : No, this is even more confusing. You wrap the definitions in extern "C", but then you mark your definitions with extern, which indicates declarations.

EDIT 3: I think I gave you bad information. extern marks declarations, not definitions. You should have code as:

// header file

extern "C" void someFunction();


// C++ file

void someFunction()
{
}



Sorry. extern marks declarations. extern "C" declares something to have C linkage, and you need to do this explicitly. In the above code, I marked someFunction to have C linkage. Then I defined the function in the C++ file.

Make sure to include the header file in the C++ file.

This post has been edited by Oler1s: 29 April 2010 - 12:39 PM

Was This Post Helpful? 0
  • +
  • -

#9 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5775
  • View blog
  • Posts: 12,587
  • Joined: 16-October 07

Re: Wrapping C/C++ Problem

Posted 29 April 2010 - 12:40 PM

Take the extern "C" out of the source file. Indeed, take all the extern out of that file. Put them in "coorctrl.h". You object code doesn't care about the extern "C" declaration.

In fact, I just realized I was a dumbass in my own example and could have done in one header what I did in two.

e.g.
#ifndef CPP_CODE_WRAPPER_H
#define CPP_CODE_WRAPPER_H

#ifdef __cplusplus
	extern "C" {
#else
	struct Circle;
	typedef struct Circle Circle;
#endif 

Circle *circleCreate(double radius);
void circleFree(Circle *);
double circleGetRadius(Circle *);
double circleGetDiameter(Circle *);
double circleGetCircumference(Circle *);
double circleGetArea(Circle *);
void circlePrint(Circle *);

#ifdef __cplusplus
	}
#endif 

#endif


Was This Post Helpful? 0
  • +
  • -

#10 ashapi  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 27-April 10

Re: Wrapping C/C++ Problem

Posted 29 April 2010 - 12:43 PM

View PostOler1s, on 29 April 2010 - 11:28 AM, said:

Please copy-paste error messages. Don't describe their existence. It may be undecipherable gibberish to you, but we can actually read them, gather information, and use that information for a diagnosis.

If you want help, don't sabotage your request by omitting information.


Errors:

/tmp/ccI4kI8b.o: In function 'main':
(path to cwd)/cct3.c:10: undefined reference to 'COOC_start()'
(path to cwd)/cct3.c:11: undefined reference to 'COOC_runOnce(void*, COOC_State*)'
(path to cwd)/cct3.c:12: undefined reference to 'COOC_stop(void*)'
collect2: ld returned 1 exit status


Quote

EDIT:

Read your the signatures of function definitions carefully. You wrote extern ..... when it should be extern "C" ....

EDIT2 : No, this is even more confusing. You wrap the definitions in extern "C", but then you mark your definitions with extern, which indicates declarations.


I thought that at most the externs before the function decalarations were redundant but I left them in when I posted before. I removed them, leaving the extern "C" wrap, and I get the exact same errors.

Thanks,

Andrew
Was This Post Helpful? 0
  • +
  • -

#11 Oler1s  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1395
  • View blog
  • Posts: 3,884
  • Joined: 04-June 09

Re: Wrapping C/C++ Problem

Posted 29 April 2010 - 12:44 PM

What I was actually thinking of was:

C header file:

void someFunction();
int anotherFunction(int a, int B)/>;



C++ source file:

//C++ headers
#include <iostream>
#include <string>

//C header
extern "C" {
#include <interface.h>
}

void someFunction()
{
//....
}

int anotherFunction(int a, int B)/>
{
//.....
}


This post has been edited by Oler1s: 29 April 2010 - 12:44 PM

Was This Post Helpful? 0
  • +
  • -

#12 ashapi  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 27-April 10

Re: Wrapping C/C++ Problem

Posted 29 April 2010 - 12:56 PM

View Postbaavgai, on 29 April 2010 - 11:40 AM, said:

Take the extern "C" out of the source file. Indeed, take all the extern out of that file. Put them in "coorctrl.h". You object code doesn't care about the extern "C" declaration.


That worked!

Thanks for all the help from both of you.

Andrew
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1