C/C++与Python实现混编(详细注释)

github博客传送门
csdn博客传送门

网上找了好多教程都是转载的同一个人的,并且没有讲清楚 嵌入的关键步骤,整理后今天先来点简单的.

主讲 c/c++ 编译为 .so 文件 嵌入 Python 实现混编

目录:

  1. C语言版 hello
  2. C++语言版 hello
  3. C语言版加法器 有参无返回值
  4. C语言版加法器 有参有返回值
  5. C++语言版加法器 有参无返回值
  6. C++语言版加法器 有参有返回值
  7. C++语言Class版

环境

  1. Python执行环境 (随便安装个Python版本添加 path就可以使用)
  2. c/c++ 执行环境 (我安装的是Dev-C++开发者工具 因为它小, 然后将 dev安装目录下的bin文件夹的路径添加到path环境变量即可在命令提示符使用)

如果有尝试失败的可以下载我编译好的 .so 文件尝试使用

下载链接:https://download.csdn.net/download/zhanghao3389/10723128
文件目录
所有文件夹

命令解释:
gcc c语言编译命令
g++ c++语言编译命令
参数 -o hello.so 输出 hello.so文件
参数 -shared 共享的
参数 -fPIC 告诉编绎器使用GOT和PLT的方法重定位
最后 跟上自己写的 文件名
例: gcc -o hello_c.so -shared -fPIC hello_c.c // 将 hello_c.c 编译生成了 hello_c.so 文件在当前目录下



每个代码第一行注释是当前文件名

C语言版 hello

// hello_c.c
#include<stdio.h>
#include<stdlib.h>
void hello()                       // 定义一个 hello的方法
{
    printf("hello python and c");  // 输出一段字符串
}

打开命令提示符进入当前文件夹输入命令
gcc -o hello_c.so -shared -fPIC hello_c.c
当前文件夹下生成一个 hello_c.so 文件
编写Python版调用程序
并执行Python程序

# hello_c.py
import ctypes                 # 导入ctypes包
so = ctypes.cdll.LoadLibrary  # 将包中的LoadLibrary方法赋给 so
func = so("./hello_c.so")     # 用 LoadLibrary 方法 打开当前文件夹下的 打包为 .so 格式的文件 并赋给func
func.hello()                  # 调用 func中的hello方法


C++语言版 hello

// hello_c++.cpp
#include<iostream>
using namespace std;  // 命名空间

           // 比如在C++中调用C库函数,就需要在C++程序中用extern “C”声明要引用的函数。
           // 这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。
extern "C" // extern修饰符可用于指示C或者C++函数的调用规范。
{
    void hello()                                  // 定义一个hello方法
    {
        cout << "hello python I'm cout" << endl;  // 输出一段字符串
        printf("hello python I'm printf");        // 输出一段字符串
    }
}

打开命令提示符进入当前文件夹输入命令
g++ -o hello_c++.so -shared -fPIC hello_c++.cpp
当前文件夹下生成一个 hello_c++.so 文件
编写Python版调用程序
并执行Python程序

# hello_c++.py
import ctypes                 # 导入ctypes包
so = ctypes.cdll.LoadLibrary  # 将包中的LoadLibrary方法赋给 so
func = so("./hello_c++.so")   # 用 LoadLibrary 方法 打开当前文件夹下的 打包为 .so 格式的文件 并赋给func
func.hello()                  # 调用 func中的hello方法


C语言版加法器 有参无返回值

// add_c_1.c
#include <stdio.h>  
#include <stdlib.h>  
int add(int a, int b)  // 定义一个 add方法 返回值为 int 传入两个参数 a,b 类型为 int
{
    int result;                             // 定义一个 int 类型的 result变量
    printf("you input %d and %d\n", a, b);  // 输出传入的两个参数
    result = a + b;                         // 计算两个参数相加的结果赋给 result
    printf("result is: %d", result);        // 输出计算结果后的值
}

打开命令提示符进入当前文件夹输入命令
gcc -o add_c_1.so -shared -fPIC add_c_1.c
当前文件夹下生成一个 add_c_1.so 文件
编写Python版调用程序
并执行Python程序

# add_c_1.py
import ctypes                 # 导入ctypes包
so = ctypes.cdll.LoadLibrary  # 将包中的LoadLibrary方法赋给 so
func = so("./add_c_1.so")     # 用 LoadLibrary 方法 打开当前文件夹下的 打包为 .so 格式的文件 并赋给func
func.add(6, 8)                # 调用 func中的add方法 并传值 6, 8 给它


C语言版加法器 有参有返回值

// add_c_2.c
#include <stdio.h>  
#include <stdlib.h>  
int add(int a, int b)                       // 定义一个 add方法 返回值为 int 传入两个参数 a,b 类型为 int
{
    printf("you input %d and %d\n", a, b);  // 输出传入的两个参数
    return a+b;                             // 返回计算后的值
}

打开命令提示符进入当前文件夹输入命令
gcc -o add_c_2.so -shared -fPIC add_c_2.c
当前文件夹下生成一个 add_c_2.so 文件
编写Python版调用程序
并执行Python程序

# add_c_2.py
import ctypes                 # 导入ctypes包
so = ctypes.cdll.LoadLibrary  # 将包中的LoadLibrary方法赋给 so
func = so("./add_c_2.so")     # 用 LoadLibrary 方法 打开当前文件夹下的 打包为 .so 格式的文件 并赋给func
print(func.add(6, 8))         # 调用 func中的add方法 并传值 6, 8 给它


C++语言版加法器 有参无返回值

// add_c++_1.cpp
#include<iostream>
using namespace std;  // 命名空间
           // 比如在C++中调用C库函数,就需要在C++程序中用extern “C”声明要引用的函数。
           // 这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。
extern "C" // extern修饰符可用于指示C或者C++函数的调用规范。
{
    int add(int a, int b)  // 定义一个 add方法 返回值为 int 传入两个参数 a,b 类型为 int
    {
        int result;                                                // 定义一个 int 类型的 result变量
        cout << "you input " << a << " and " << b << ", I'm cout." << endl;  // 输出传入的两个参数
        printf("you input %d and %d, I'm printf.\n", a, b);        // 输出传入的两个参数
        result = a + b;                                            // 计算两个参数相加的结果赋给 result
        cout << "result is: " << result << ", I'm cout." << endl;  // 输出计算结果后的值
        printf("result is: %d, I'm printf.\n", result);            // 输出计算结果后的值
    }
}

g++ -o add_c++_1.so -shared -fPIC add_c++_1.cpp
当前文件夹下生成一个 add_c++_1.so 文件

# add_c++_1.py
import ctypes                 # 导入ctypes包
so = ctypes.cdll.LoadLibrary  # 将包中的LoadLibrary方法赋给 so
func = so("add_c++_1.so")     # 用 LoadLibrary 方法 打开当前文件夹下的 打包为 .so 格式的文件 并赋给func
func.add(66, 88)              # 调用 func中的add方法 并传值 66, 88 给它


C++语言版加法器 有参有返回值

// add_c++_2.cpp
#include<iostream>
using namespace std;  // 命名空间
           // 比如在C++中调用C库函数,就需要在C++程序中用extern “C”声明要引用的函数。
           // 这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。
extern "C" // extern修饰符可用于指示C或者C++函数的调用规范。
{
    int add(int a, int b)  // 定义一个 add方法 返回值为 int 传入两个参数 a,b 类型为 int
    {
        cout << "you input " << a << " and " << b << ", I'm cout." << endl;  // 输出传入的两个参数
        printf("you input %d and %d, I'm printf.\n", a, b);                  // 输出传入的两个参数
        return a+b;                                                          // 返回a+b后的值
    }
}

g++ -o add_c++_2.so -shared -fPIC add_c++_2.cpp
当前文件夹下生成一个 add_c++_2.so 文件

# add_c++_2.py
import ctypes                 # 导入ctypes包
so = ctypes.cdll.LoadLibrary  # 将包中的LoadLibrary方法赋给 so
func = so("add_c++_2.so")     # 用 LoadLibrary 方法 打开当前文件夹下的 打包为 .so 格式的文件 并赋给func
print(func.add(66, 88))       # 调用 func中的add方法 并传值 66, 88 给它


C++语言Class版

// c++class.cpp
#include <iostream>  
using namespace std;                            // 命名空间
  
class HelloAndAdd                               // 定义一个 hello的方法 和一个 add的方法
{
    public:  
        void hello();                           // 定义一个hello的方法 无参无返回值
        void add(int a, int b);                 // 定义一个 add 方法 传入两个值 进行加法运算
};  
void HelloAndAdd::hello()                       // 定义HelloAndAdd里 hello方法的主体
{
    cout<<"Hello C++ class , I'm cout."<<endl;  // 输出
    printf("Hello C++ class , I'm printf.");    // 输出
}
  
void HelloAndAdd::add(int a, int b)                            // 定义HelloAndAdd里 add 方法的主体
{
    int result;                                                // 定义一个result 接收传入两个参数的结果
    cout << "you input " << a << " and " << b << ", I'm cout." << endl;  // 输出传入的两个参数
    printf("you input %d and %d, I'm printf.\n", a, b);        // 输出传入的两个参数
    result = a+b;                                              // 计算两个参数相加的结果赋给 result
    cout << "result is: " << result << ", I'm cout." << endl;  // 输出计算结果后的值
    printf("result is: %d, I'm printf.\n", result);            // 输出计算结果后的值
    
}

           // 比如在C++中调用C库函数,就需要在C++程序中用extern “C”声明要引用的函数。
           // 这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。
extern "C" // extern修饰符可用于指示C或者C++函数的调用规范。
{
    HelloAndAdd haa;           // 实例化HelloAndAdd对象为 haa
    void hello()               // 定义Python访问该方法的 方法名
    {
        haa.hello();           // 传入上述方法执行的主体 等价于 return haa.hello();
    }
    void add(int a, int b)     // 定义Python访问该方法的 方法名 并传入参数
    {
        return haa.add(a, b);  // 传入上述方法执行的主体 并传入参数
    }
}

g++ -o c++class.so -shared -fPIC c++class.cpp
当前文件夹下生成一个 c++class.so 文件

# c++class.py
import ctypes                 # 导入ctypes包
so = ctypes.cdll.LoadLibrary  # 将包中的LoadLibrary方法赋给 so
func = so("./c++class.so")    # 用 LoadLibrary 方法 打开当前文件夹下的 打包为 .so 格式的文件 并赋给func
func.hello()                  # 调用 func中的hello方法
print('\n----------')
func.add(10, 20)              # 调用 func中的add方法 并传入参数 10, 20

编写不易,求助攻一个...

print_r('点个赞吧');
var_dump('点个赞吧');
NSLog(@"点个赞吧!")
System.out.println("点个赞吧!");
console.log("点个赞吧!");
print("点个赞吧!");
printf("点个赞吧!\n");
cout << "点个赞吧!" << endl;
Console.WriteLine("点个赞吧!");
fmt.Println("点个赞吧!")
Response.Write("点个赞吧");
alert(’点个赞吧’)
posted @ 2018-10-16 10:42  账号  阅读(3466)  评论(0编辑  收藏  举报