Wednesday, March 21, 2012

C Call C++

[1] ParaShift.com
     isocpp.org/wiki/faq/mixing-c-and-cpp
[2] Bytes.com
[3] research.att.com


From [3]
------------------------
 // C++ code:
 extern "C" void f(int);
 void f(int i){
  // ...
 }
 /* C code: */
 void f(int);
 void cc(int i){
  f(i);
  /* ... */
 }

// C++ code:
 class C {
  // ...
  virtual double f(int);
 };

 extern "C" double call_C_f(C* p, int i) // wrapper function
 {
  return p->f(i);
 }

 /* C code: */
 double call_C_f(struct C* p, int i);
 void ccc(struct C* p, int i){
  double d = call_C_f(p,i);
  /* ... */
 }


 // C++ code:
 void f(int);
 void f(double);

 extern "C" void f_i(int i) { f(i); }
 extern "C" void f_d(double d) { f(d); }

 /* C code: */
 void f_i(int);
 void f_d(double);

 void cccc(int i,double d){
  f_i(i);
  f_d(d);
  /* ... */
 }




From [1]
-----------------------------
main.cpp

// This is C++ code
#include "Fred.h"
int main()
{
  Fred fred;
  c_function(&fred);
} 



c-function.c

/* This is C code */
#include "Fred.h"

void c_function(Fred* fred){
   unsigned char lc;

   cplusplus_callback_function(fred);
   lc=Cplusplus_CallbackFunction_Wilma(456,fred);
   printf("return of C++ Wilma: %d\n",lc);
} 


Fred.cpp

// This is C++ code
#include "Fred.h"
#include  /*std::cout<<*/

//Fred::Fred() : a_(0) { }
Fred::Fred() { }

void Fred::wilma(int a) { std::cout<<"wilma(arg) print arg "<        

Fred* cplusplus_callback_function(Fred* fred){
  fred->wilma(123);
  return fred;
} 

//Provide access of C++ methods from C code.
unsigned char Cplusplus_CallbackFunction_Wilma(int a, Fred* fred){
  fred->wilma(a);
  return(0);
} 


Fred.h

 
/* This header can be read by both C and C++ compilers */
 #ifndef FRED_H
 #define FRED_H

 #ifdef __cplusplus
   class Fred {
   public:
     Fred();
     void wilma(int);
   private:
     int a_;
   };
 #else
   typedef struct Fred  Fred;

 #endif


 #ifdef __cplusplus
 extern "C" {
 #endif


 #if defined(__STDC__) || defined(__cplusplus)
   extern void c_function(Fred*);   /* ANSI C prototypes */
   extern Fred* cplusplus_callback_function(Fred*);
   extern unsigned char Cplusplus_CallbackFunction_Wilma(int a, Fred* fred);
 #else
   extern void c_function();        /* K&R style */
   extern Fred* cplusplus_callback_function();
 #endif

 #ifdef __cplusplus
 }

 #endif
 #endif /*FRED_H*/





Makefile
DESTDIR  = ./
PROGRAM = $(DESTDIR)/CCallCplusplus
SRCDIR = ./
INCL = -I ./
CP = g++
C = gcc
#C = arm-none-linux-gnueabi-g++

OBJS := $(addprefix $(DESTDIR)/,main.o Fred.o c-function.o)
DEBUG = -g
CFLAGS = -Wall $(DEBUG)

all:$(PROGRAM)

$(PROGRAM): $(OBJS)
 $(CP) -o $(PROGRAM) $(OBJS) -lpthread

$(DESTDIR)/%.o:$(SRCDIR)/%.cpp
 $(CP) -c $(CFLAGS) $< -o $@ $(INCL)

$(DESTDIR)/%.o:$(SRCDIR)/%.c
 $(C) -c $(CFLAGS) $< -o $@ $(INCL)

clean :
 rm -f $(OBJS)
 rm -f $(PROGRAM)



Result:

wilma(arg) print arg 123
wilma(arg) print arg 456
return of C++ Wilma: 0

Tuesday, March 6, 2012

Shell exit on Error

[1] A little madness
[2] Fvue.nl WiKi

Bash Tip: Exit on Error

Back in my post Your Next Programming Language I mentioned I would post occassional tips about bash scripting. As soon as I started writing my next script, it occured to me: the first thing I always do when writing a new bash script is set the errexit option:

set -e

This option makes your script bail out when it detects an error (a command exiting with a non-zero exit code). Without this option the script will plough on, and mayhem often ensues. In all the noise generated it can be a pain to found the root cause of the problem. So I make it a rule to set this option and fail as early as possible.


[2]
----------------------
Exit on error

Bash can be told to exit immediately if a command fails. From the bash manual ("set -e"):

"Exit immediately if a simple command (see SHELL GRAMMAR above) exits with a non-zero status. The shell does not exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test in an if statement, part of a && or || list, or if the command's return value is being inverted via !. A trap on ERR, if set, is executed before the shell exits."

To let bash exit on error, different notations can be used:

Specify `bash -e' as shebang interpreter
Start shell script with `bash -e'
Use `set -e' in shell script
Use `set -o errexit' in shell script
Use `trap exit ERR' in shell script

Specify `bash -e' as the shebang interpreter