Skip to content

techtrendings.com

Let's explore

Menu
Menu

Calling C Code from C++ – Mix C and C++

Posted on January 8, 2022 by Avidlearner
pexels.com

If you have a project which is written in C/C++ where you are seeing the parts of code has been implemented in C
and some part in C++.Then you might have observed that user might have the need to call C function from C++ code and vice-versa.

Let’s see how we can do this.

Requirement: Compilers should be Compatible
The first requirement for mixing code is that the C and C++ compilers you are using must be compatible.
They must, for example, define basic types such as int, float or pointer in the same way.

The probably easiest way to use C functionality in a C++ program is to simply compile the C code as C++ code.
This will, however, not work reliably.

So, we have to compile the C code as C, and the C++ code as C++.

For simplicity, let’s assume we have a function void fun(int) that has been defined in one source file and
gets called in another source file.

In C, the compiler generates a simple symbol fun for that function – this is defined in the C standard.
In C++, we can have much more than one function named fun: we have different namespaces, classes with
member functions, and overloaded functions that take different parameters. Therefore, the C++ compiler
can not simply create a symbol fun. It has to generate names that contain all that information. The
process is called name mangling and is not standardized.

Let’s assume, fun is a C function which we want to call from main in our C++ program:

//main.cpp 

#include "fun.h"
int main()
 {
  fun(14);
 }

//fun.h
void fun(int);
#include <stdio.h>

//fun.c
void fun(int x) {
  printf("%d", x);
}

When we compile the whole thing, the linker will give us an error: The C++ compiler will see the declaration of void fun(int) and the call to that function and generate a mangled name, say, void@fun(int). The C compiler will simply generate the symbol foo. The linker will, therefore, complain that it can not find void@fun(int), because that symbol simply does not exist.

Accessing C Code from Within C++ Source
The C++ language provides a “linkage specification” with which you declare that a function or object follows
the program linkage conventions for a supported language. The default linkage for objects and functions is C++.
All C++ compilers also support C linkage, for some compatible C compiler.

When you need to access a function compiled with C linkage (for example, a function compiled by the C compiler,
declare the function to have C linkage. Even though most C++ compilers do not have different linkage for C and
C++ data objects, you should declare C data objects to have C linkage in C++ code.

Linkage Specifications
Use one of the following notations to declare that an object or function has the linkage of language
language_name:

extern “language_name” declaration ;
extern “language_name” { declaration ; declaration ; … }

The first notation indicates that the declaration (or definition) that immediately follows has the linkage of language_name. The second notation indicates that everything between the curly braces has the linkage of language_name, unless declared otherwise. Notice that you do not use a semicolon after the closing curly brace in the second notation.

You can nest linkage specifications, but the braces do not create scopes. Consider the following example:

extern "C" {
    void f1();              // C linkage
    extern "C++" {
        void g1();          // C++ linkage
        extern "C" void h1(); // C linkage
        void g2();         // C++ linkage
    }
    extern "C++" void k1(); // C++ linkage
    void m1();              // C linkage
}
Just declare the C function extern "C" (in your C++ code) and call it (from your C or C++ code). For example:

    // C++ code
    extern "C" void f1(int); // one way
    extern "C" {    // another way
        int g1(double);
        double h1();
    };
    void example(int i, double d)
    {
        f(i);
        int ii = g1(d);
        double dd = h1();
        // ...
    }
The definitions of the functions may look like this:

    /* C code: */
    void f1(int i)
    {
        /* ... */
    }
    int g1(double d)
    {
        /* ... */
    }
    double h1()
    {
        /* ... */
    }
Note that C++ type rules, not C rules, are used. So you can’t call function declared extern "C" with the wrong number of arguments. For example:

    // C++ code
    void more_code(int i, double d)
    {
        double dd = h1(i,d); // error: unexpected arguments
        // ...
    }
How do I call a C++ function from C?  
Just declare the C++ function extern "C" (in your C++ code) and call it (from your C or C++ code). For example:

    // C++ code:
    extern "C" void f1(int);
    void f1(int i)
    {
        // ...
    }
Now f1() can be used like this:

    /* C code: */
    void f1(int);
    void cc(int i)
    {
        f1(i);
        /* ... */
    }
Naturally, this works only for non-member functions. If you want to call member functions (incl. virtual functions) from C, you need to provide a simple wrapper. For example:

    // C++ code:
    class C {
        // ...
        virtual double f1(int);
    };
    extern "C" double call_C_f(C* p, int i) // wrapper function
    {
        return p->f1(i);
    }
Now C::f1() can be used like this:

    /* 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);
        /* ... */
    }

Related

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • Implement Trie Data Structure in C++- LeetCode
  • How TLS Works
  • C++ – Factory Design Pattern – Creation Design Pattern
  • C++ – Strategy Design Pattern – Behavioral Design Pattern
  • LFU Cache Implementation – LeetCode

Recent Comments

  • automatically like friends photos on instagram on Program to find unpaired element in an Array in C++|Leetcode |techtrendings
  • Twicsy on Program to find unpaired element in an Array in C++|Leetcode |techtrendings

Archives

  • January 2023
  • November 2022
  • August 2022
  • June 2022
  • May 2022
  • March 2022
  • February 2022
  • January 2022

Categories

  • Algorithm
  • Algorithm
  • C++
  • Design Patterns
  • Multithreading
  • OS Concepts
  • Programming
  • Uncategorized

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org

Join Our Mailing List for the Latest News and Updates.

© 2023 techtrendings.com | Powered by Superbs Personal Blog theme