zoukankan      html  css  js  c++  java
  • 10 python 扩展

    说起来扩展,基本就是在其他语言里调用C或者C++,因为这两个是效率最高的代码,而其他大多都是另外又封装的,所以效率较低。

    当出现语言本身无法解决的效率问题时,就需要扩展调用其他代码。

    因为我自己会C++,所以我就只记录调用C++。

    其中调用DLL最为简单,所以在此自己mark一下。

    正文开始:

    C++中生成DLL就不废话了。需要特别注意的是据我所知VS2010之前的版本貌似只能编译成32位的DLL,但是我的电脑安装的是64位的python,调用32位的就会出错。

    解决办法就是用VS2010,在2010中可以编译成64位的DLL。具体方法是在上边的win32中选择编辑新的方式,里边可以选。

    接下来举个简单例子

     1 //hello.h
     2 #ifdef EXPORT_HELLO_DLL
     3 #define HELLO_API __declspec(dllexport)
     4 #else
     5 #define HELLO_API __declspec(dllimport)
     6 #endif
     7 extern "C"
     8 {
     9  HELLO_API int IntAdd(int , int);
    10 }
    11 
    12 //hello.cpp
    13 #define EXPORT_HELLO_DLL
    14 #include "hello.h"
    15 HELLO_API int IntAdd(int a, int b)
    16 {
    17  return a + b;
    18 }

    上述是两个文件,也就是C++中需要编译DLL的文件。

    1 from ctypes import *
    2 dll = cdll.LoadLibrary('hello.dll')
    3 ret = dll.IntAdd(2, 4)
    4 print(ret)

    上述是调用DLL文件的代码,其实就是用到了ctypes库。

    以上是一个"hello world"级别的程序,实际运用中更多的需要传递数据结构、字符串等,才能满足我们的需求。那么本示例将展示,如何传递数据结构参数,以及如何通过数据结构获取返回值。

     1 //hello.h
     2 #ifdef EXPORT_HELLO_DLL
     3 #define HELLO_API __declspec(dllexport)
     4 #else
     5 #define HELLO_API __declspec(dllimport)
     6 #endif
     7  
     8 #define ARRAY_NUMBER 20
     9 #define STR_LEN 20
    10  
    11 struct StructTest
    12 {
    13  int number;
    14  char* pChar;
    15  char str[STR_LEN];
    16  int iArray[ARRAY_NUMBER];
    17 };
    18  
    19 extern "C"
    20 {
    21  //HELLO_API int IntAdd(int , int);
    22  HELLO_API char* GetStructInfo(struct StructTest* pStruct);
    23 }
    24 
    25 //hello.cpp
    26 #include <string.h>
    27 #define EXPORT_HELLO_DLL
    28 #include "hello.h"
    29  
    30 HELLO_API char* GetStructInfo(struct StructTest* pStruct)
    31 {
    32  for (int i = 0; i < ARRAY_NUMBER; i++)
    33  pStruct->iArray[i] = i;
    34  pStruct->pChar = "hello python!";
    35  strcpy (pStruct->str, "hello world!");
    36  pStruct->number = 100;
    37  return "just OK";
    38 }

    GetStructInfo这个函数通过传递一个StructTest类型的指针,然后对对象中的属性进行赋值,最后返回"just OK".

    编写Python调用代码如下,首先在Python中继承Structure构造一个和C DLL中一致的数据结构StructTest,然后设置函数GetStructInfo的参数类型和返回值类型,最后创建一个StructTest对象,并将其转化为指针作为参数,调用函数GetStrcutInfo,最后通过输出数据结构的值来检查是否调用成功:

    from ctypes import *
    ARRAY_NUMBER = 20;
    STR_LEN = 20;
    #define type
    INTARRAY20 = c_int * ARRAY_NUMBER;
    CHARARRAY20 = c_char * STR_LEN;
    #define struct
    class StructTest(Structure):
      _fields_ = [
        ("number", c_int),
        ("pChar", c_char_p),
        ("str", CHARARRAY20),
        ("iArray", INTARRAY20)
            ]
    #load dll and get the function object
    dll = cdll.LoadLibrary('hello.dll');
    GetStructInfo = dll.GetStructInfo;
    #set the return type
    GetStructInfo.restype = c_char_p;
    #set the argtypes
    GetStructInfo.argtypes = [POINTER(StructTest)];
    objectStruct = StructTest();
    #invoke api GetStructInfo
    retStr = GetStructInfo(byref(objectStruct));
    #check result
    print "number: ", objectStruct.number;
    print "pChar: ", objectStruct.pChar;
    print "str: ", objectStruct.str;
    for i,val in enumerate(objectStruct.iArray):
      print 'Array[i]: ', val;
    print retStr;

    最后要说一点,这些内容不是原创,只是我用别人的方法,自己验证时候遇到的问题,比如64位DLL的问题。

    http://blog.csdn.net/bluehawksky/article/details/39082125 更详细的各种数据结构的传递可以看这个。

  • 相关阅读:
    Button与Submit调用前台与后台代码的方法
    ASP.NET前台代码绑定后台变量方法总结
    点击后禁用提交按钮
    SilverLight3测试(1): Message: AG_E_NETWORK_ERROR
    SilverLight 问题解决
    XmlSerializers.dll.deploy 未成功
    命令模式泛型?问题?
    SilverLight 收藏(2009年3月27日)
    在Web安装工程中为虚拟目录指定不同的本地路径
    Silverlight 3 Sample Application: Slidentity
  • 原文地址:https://www.cnblogs.com/lixiaofou/p/7820380.html
Copyright © 2011-2022 走看看