zoukankan      html  css  js  c++  java
  • python作为一种胶水和c/c++

    如果需要用 Python 调用 C/C++ 编写的第三方库,只需要一个脚本语言来粘合它们。这个时候,用 Python ctypes 可以很方便地实现调用。

    StackOverflow 上的 Calling C/C++ from python 这个主题介绍了 ctypes 最简单的入门方法,概括如下:

    1. 如果是 C 函数库,则直接 load 这个库,然后调用即可;
    2. 如果是 C++ 函数库,则需要用 extern 关键字封装一个供 C 使用的函数,即把类隐藏到一些 C 风格的函数里,然后用 extern 标明这些函数,以方便外部调用。

    这两种方法里,弄懂了 ctypes 调用 C++ 库的方法,就会用 ctypes 调用 C 函数库,对 C++ 库的基本方法如下。

    例如,有一个 C++ 类 Foo:

    #include <iostream>     
    class Foo{     
        public:                  
            void bar(){             
                std::cout << "Hello" << std::endl;
            }
    };

    再封装出下面 C 风格的接口函数:

    extern "C" {     
        Foo* Foo_new(){         
            return new Foo(); 
        }     
        void Foo_bar(Foo* foo){ 
            foo->bar(); 
        }
    }

    把上面的代码编译成动态链接库:

    g++ -c -fPIC foo.cpp -o foo.o
    g++ -shared -Wl,-soname,libfoo.so -o libfoo.so  foo.o

    ,然后再用 Python 写的代码来调用这个类,你可以把上面两个 C 接口函数写成 Python 类,或是直接调用:

    from ctypes import cdll 
    lib = cdll.LoadLibrary('./libfoo.so')  
    
    class Foo(object):     
        def __init__(self):         
            self.obj = lib.Foo_new()     
        def bar(self):
            lib.Foo_bar(self.obj)
    

    ,然后就可以在 Python 脚本里调用这个 Python 类了:

    f = Foo()
    f.bar() #and you will see "Hello" on the screen

    在 Windows 下用 Python ctypes 的方法和上面一样,只是有下面两点需要注意一下:

    1. 在编写 Python 代码时,刚开始链接所需的动态链接库时,最好使用绝对路径来 load,以减少出错概率,加快调试速度

      在我按上面的方法编写好了上述代码时,一运行脚本,则提示如下错误信息:

      $ python Linkcpp.py
      Traceback (most recent call last):
        File "Linkcpp.py", line 2, in <module>
          lib = cdll.LoadLibrary('./LinkExample')
        File "C:Python27libctypes\__init__.py", line 431, in LoadLibrary
          return self._dlltype(name)
        File "C:Python27libctypes\__init__.py", line 353, in __init__
          self._handle = _dlopen(self._name, mode)
      WindowsError: [Error 126]

      这是因为我在代码里是使用了这样的代码来导入动态链接库:

      from ctypes import cdll 
      lib = cdll.LoadLibrary('./LinkExample')
      

      如果把 ./LinkExample 这句换成 Windows 下的绝对路径 E:/PythonCode/LinkCpp/LinkExample,则没有错误提示了。当然,你直接把 ./LinkExample 换成 LinkExample 也可以找到该链接库。

      所以,刚开始的时候,使用绝对路径,以确保你不会纠结于能不能找到链接库之类的问题。

      在运行上述脚本的时候,出现 WindowsError: [Error 126] 的错误,无非就是两个原因

      • 你的 DLL 没有正确地被加载;
      • 你的 DLL 依赖的其它 DLL 没有被找到或是加载失败。

      另外,注意一下,Windows 下因为库分为 lib 和 dll 两个文件,所以可以只输入库的名称即可,比如说你要链接 LinkExample.dll 库,则可以在 ctypes 里只需要声明链接名为 LinkExample 库即可。

    2. 如果是 C++ 写的库,需要用上 extern 关键字,这个和一般的供 C 调用的 C++ 库头文件是一样的

      在 extern 声明的函数里,可以使用 C++ 里 C 没有的关键字,比如我的函数就是这样声明的:

      externint linkExample(constint index, constchar* name);

      上面代码可以从 Python 调用运行。

      extern:extern可置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量或函数时,在其它模块中寻找其定义。另外,extern也可用来进行链接指定。

    亲自实现

    c++  

    g++编译 g++ -o libpycallclass.so -shared -fPIC ex.cpp 

    1. #include <iostream>  
      using namespace std;  
        
      class TestLib  
      {  
          public:  
              void display();  
              void display(int a);  
      };  
      void TestLib::display() {  
          cout<<"First display"<<endl;  
      }  
        
      void TestLib::display(int a) {  
          cout<<"Second display:"<<a<<endl;  
      }  
      extern "C" {  
          TestLib obj;  
          void display() {  
              obj.display();   
            }  
          void display_int() {  
              obj.display(2);   
            }  
      }

    python 调用

    import ctypes  
    so = ctypes.cdll.LoadLibrary   
    lib = so("./libpycallclass.so")   
    print 'display()'  
    lib.display()  
    print 'display(100)'  
    lib.display_int(100)  

    参考资料:

    stackoverflow.com  calling-c-c-from-python

    python调用c/c++相关工具:Boost.python 

    二次转发:http://blog.csdn.net/suwei19870312/article/details/18181675

  • 相关阅读:
    愿你出走半生,归来多赚点钱
    喝下这碗毒鸡汤:作为一个『乖』学生,请一定要以学业为主!
    劝你理财,是我最大的温柔-lip师兄
    大半夜客户问我为什么这么拼,我给她算了笔账,她嚎啕大哭......
    女人为什么要经济独立
    定投6年以亏损收场,他到底做错了什么
    你的死工资,正在拖垮你&一辈子需要花多少钱
    字符串的长度
    泥塑课
    最大的数
  • 原文地址:https://www.cnblogs.com/learn-to-rock/p/5447912.html
Copyright © 2011-2022 走看看