将C ++库用于C应用程序

时间:2014-06-17 10:30:17

标签: c++ c

我在C中有一个命令行(+ HTTP接口)音频应用程序,目前正在Mac OSX上用gcc编译,但我想保持这个应用程序与linux兼容。

但是,我想使用freeverb3库。这是用C ++编写的。我宁愿不将我的所有代码转换为C ++。我(我认为)不需要从C ++调用任何C代码,也不需要在C代码中使用C ++对象。简单的方法调用传递双精度数组和几个整数作为参数将是我在主应用程序和C ++代码的交互方面所需的全部内容。

从一些快速的谷歌搜索,似乎我可以编写一个C ++接口模块,然后可以公开一些我可以调用以使用freeverb3的兼容函数。我已经编写了一个微观示例,看看它是如何工作的。在这个例子中,我有一个名为test.cpp的虚拟c ++文件:

#include <iostream>
using namespace std;

class test_class
{
  int a;

  public:

    int get_a();
    void set_a( int v );
};

int test_class::get_a()
{
  return a;
}

void test_class::set_a( int v )
{
  a = v;
}

static test_class *c;

extern "C"
{
  void init();
  void set( int v );
  int get();
}

void init()
{
  c = new test_class();
}

void set( int v )
{
  c->set_a( v );
}

int get()
{
  return c->get_a();
}

我有一个调用函数的虚拟c文件:

#include <stdio.h>

/* Forward declaratoins for extern "C" functions in C++ code */

void init();
int get();
void set( int v );

/* C language code that references functions in C++ code */

int main()
{
  init();

  set( 55 );
  printf( "value: %d\n", get() );
  set( get() + 12 );
  printf( "value: %d\n", get() );
  return 0;
}

而且,我有一个创建可执行文件的makefile。

test: test.o user.o
    g++ -o test user.o test.o

test.o: test.cpp
    g++ -c test.cpp

user.o: user.c
    gcc -c user.c

这是使用C语言的C ++代码的好方法吗?是否有更好/更复杂/更传统的方式来实现这一目标?

5 个答案:

答案 0 :(得分:2)

你可能想以另一种方式思考它。 用C ++编写更高级别的应用程序,无需复杂地调用所需的C ++库,并从C ++级别调用所有当前的C模块。

恕我直言,这比使用高级别的C更容易实现。

答案 1 :(得分:1)

如果您打算从C使用多个C ++对象,则需要将额外的实例指针(this)传递给C包装器函数:

struct A {
    A();
    ~A();
    void set(int);
};

C包装器:

extern "C"
{
    struct A* a_create(void);
    void a_destroy(struct A*);
    void a_set(struct A*, int);
}

您可能还希望捕获C包装函数中的所有C ++异常并将它们转换为错误代码。

答案 2 :(得分:0)

将指针传递给对象,而不是使用静态变量。

C ++类:

class Foo
    {
    public:
        void doStuff();
    };

通用包含文件:

#ifdef __cplusplus
extern "C"
    {
#endif
    void Foo_doStuff(void* handle);

    void* Foo_create();
    void Foo_destroy(void* handle);

#ifdef __cplusplus
    }
#endif

包装函数

void Foo_doStuff(void* handle)
    {((Foo*)handle)->doStuff();}

void* Foo_create()
    {return new(nothrow)Foo;}

void Foo_destroy(void* handle)
    {delete (Foo*)handle;}

答案 3 :(得分:0)

不确定这是从C到C ++,但值得研究Swig

答案 4 :(得分:0)

在C ++中创建一个extern "C"包装器,例如

// myWrapper.h
#ifdef __cplusplus
extern "C"
{
#endif

     void func1(void);
     int  func2(void);
     void func3(char const *str_ptr, size_t len);

#ifdef __cplusplus
}
#endif

// myWrapper.cpp
#include "myWrapper.h"
#include "your_cpp_library.h"

void func3(char const *str_ptr, size_t len)
{
    std::string s(str_ptr, str_ptr + len);

    call_cpp_function(s);
}
// etc.

在您的C代码中#include "myWrapper.h"并调用这些函数。确保:

  • myWrapper.h中的代码保留在C和C ++的公共子集中
  • 您不进行任何跨境资源分配

后者可能会起作用,但最好避免它安全。后一点意味着如果要分配内存,则必须由同一侧分配和释放;例如你不能让C ++端调用malloc并指向C端,然后让C端调用free。你必须将指针传回给分配它的人,让他们释放它。

重要:正如Alf在评论中所说,在进行C-C ++互连时,您必须在C ++中使用main()并使用C ++链接器。这不是一个很大的障碍;您可以将C代码的main()函数重命名为main2(),并让C ++代码执行extern "C" int main2();并调用它。

相关问题