python混合编程,so库、jar包、pyppeteer

依赖安装

pip install JPype1 rpy2 julia pyppeteer

julia
using Pkg
Pkg.add("PyCall")
Pkg.build("PyCall")
exit()

目录结构

  • 📁 src
    • 📁 c
      • 📄 main.c
    • 📁 java
      • 📁 org
        • 📁 example
          • 📁 demo
            • 📄 CryptoUtil.java
    • 📁 js
      • 📄 main.html
    • 📁 julia
      • 📄 main.jl
    • 📁 r
      • 📄 main.r
    • 📁 shell
      • 📄 main.sh
  • 📄 main.py

代码

先说这些代码都干啥了,c代码用来数字转大写36进制,java写了RSA加解密,js打印浏览器信息,julia和r都是操作矩阵,shell用来编译c和java,python调用以上几种语言。
也就是说直接在main.py的目录下运行之就能一步到位调用每一个文件的代码。
系统、python等等版本都会在调用shell时获取到,见文末运行结果。

main.c

#include <math.h>
#include <string.h>
#include <stdlib.h>

#define BASE 36

char *to36based(unsigned long num)
{
    int len = (int)(ceil(log(num + 1) / log(BASE))) + 1; // 换底公式求出36进制串可见字符数附加一个\0
    char *ret = (char *)malloc(sizeof(char) * len);      // 开辟内存空间
    memset(ret, 0, sizeof(char) * len);                  // 0值填充
    int i = len - 2;
    while (num != 0) // 辗转除法
    {
        char c = (num % BASE);
        c += (c < 10 ? '0' : ('A' - 10));
        ret[i--] = c;
        num = num / BASE;
    }
    return ret; // 转36进制字符串,输出指针
}

int strDestory(char *pointer)
{
    if (pointer != NULL)
    {
        free(pointer); // 释放指针
    }
}

CryptoUtil.java

package org.example.demo;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;

public abstract class CryptoUtil {
    private static final String CRYPTO_ALGORITHM = "RSA";
    private static final int KEY_SIZE = 1024;
    private static final char CHAR_ZERO = '0';

    public static KeyPair getKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(CRYPTO_ALGORITHM);
        keyPairGenerator.initialize(KEY_SIZE);
        return keyPairGenerator.generateKeyPair();
    }

    /**
     * 加密并Base64编码。
     *
     * @param content   明文字符串
     * @param publicKey 公钥
     * @return Base64密文。
     */
    public static String encrypt(String content, RSAPublicKey publicKey)
        throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException,
        BadPaddingException {
        Cipher cipher = Cipher.getInstance(CRYPTO_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] bytesContent = content.getBytes(StandardCharsets.US_ASCII);
        byte[] res = cipher.doFinal(bytesContent);
        return java.util.Base64.getEncoder().encodeToString(res);
    }

    /**
     * Base64格式密文转换为明文字符串。
     *
     * @param content    Base64密文
     * @param privateKey 私钥
     * @return 明文。
     */
    public static String decrypt(String content, PrivateKey privateKey)
        throws NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException,
        InvalidKeyException  {
        String ret = null;
        Cipher cipher = Cipher.getInstance(CRYPTO_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] bytesContent = java.util.Base64.getDecoder().decode(content.getBytes());
        byte[] res = cipher.doFinal(bytesContent);
        ret = new String(res);
        return ret;
    }

    public static PrivateKey str2privateKey(String key)
        throws NoSuchAlgorithmException, InvalidKeySpecException {
        PrivateKey ret = null;
        byte[] byteKey = Base64.getDecoder().decode(key);
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(byteKey);
        KeyFactory keyFactory = KeyFactory.getInstance(CRYPTO_ALGORITHM);
        ret = keyFactory.generatePrivate(spec);
        return ret;
    }
}

main.html

<!DOCTYPE html>
<html lang="en">
<!-- body里面什么都没有,但是python要获取body里面的内容,这些内容是js插进去的 -->
<body>
</body>
<script>
    document.body.innerHTML = navigator.userAgent; // 动态网页,将浏览器信息插入dom节点
</script>

</html>

main.jl

using PyCall

function label(mat::AbstractMatrix, dims::Int=2)::Matrix
    ret::Matrix = zeros(size(mat))
    amax = argmax(mat, dims=dims)
    for v ∈ amax
        ret[v] = 1
    end
    return mat .* ret
end

main.r

transpose <- function(data,width,height) {
    M = matrix(data, nrow = height, ncol = width, byrow = TRUE)
    return(t(M))
}
still <- function(data,width,height) {
    M = matrix(data, nrow = height, ncol = width, byrow = TRUE)
    return(M)
}

main.sh

echo 'encoding utf-8'
cat /proc/version
uname -a
python --version
gcc --version
R --version
julia -v
java --version
echo "Shell script path:" $(cd `dirname $0`; pwd)
pip list
echo "========分界线========"
# 创建二进制文件输出目录
mkdir -p ./target/.classes
# 编译c代码
gcc -shared -o ./target/main.so -fPIC ./src/c/main.c 
# 编译java代码
javac @.list -d ./target/.classes -encoding utf-8
cd ./target/.classes
# 制作jar包
jar -cvf ../main.jar .
echo "========分界线========"

main.py

import asyncio
import ctypes
import os

import jpype
import pyppeteer
import rpy2.robjects as robjects

from julia import Julia

# 准备工作


async def main():
    browser = await pyppeteer.launch(
        headless=False, dumpio=True, autoClose=False,
        executablePath="/usr/bin/chromium",  # 浏览器安装路径
        args=["--no-sandbox", "--disable-infobars"]
    )  # 声明浏览器
    page = await browser.newPage()  # 打开新的标签页
    abspath = os.path.abspath("./src/js/main.html")  # 获取网页绝对路径
    await page.goto("file://"+abspath)  # 设置网页路径
    text = await page.evaluate('() => document.body.innerHTML')  # 注入一条js
    print(text)  # 获取js输出
    await browser.close()  # 关掉浏览器


if __name__ == "__main__":
    java_files = []
    for root, _, files in os.walk('src/java', topdown=True):
        for file in files:
            if file.endswith(".java"):  # 查找java文件
                java_files.append(os.path.join(root, file))
    with open('.list', 'w') as file:
        file.write('\n'.join(java_files))  # 写入.list文件供java编译用

    # shell
    result = os.popen("./src/shell/main.sh")  # 调用shell脚本输出环境信息,并编译c和java代码
    lines = result.readlines()  # 获取shell输出
    for line in lines:
        print(line, end="")  # 把shell输出打印在控制台上,这些line自带换行所以end=""

    # c
    clib = ctypes.cdll.LoadLibrary("./target/main.so")  # 加载刚刚编译好的so库
    num = int(10000)
    to36based = clib.to36based
    strDestory = clib.strDestory
    to36based.restype = ctypes.POINTER(ctypes.c_char)  #在python中指定c函数返回类型
    res = to36based(num)  # 转36进制
    string = ctypes.cast(res, ctypes.c_char_p).value
    string = str(string, encoding='ascii')
    print(string, ":", res)
    code = strDestory(res)  # c没垃圾回收,需要手动把内存释放掉
    print(code)

    # R
    robjects.r.source("./src/r/main.r")  # 调用r文件
    mat = robjects.r["transpose"]([0, 1, 2, 3, 4, 5], 3, 2)
    print(type(mat))
    print(mat)
    with open("./src/r/main.r", "r") as script:  # 直接读取r代码
        robjects.r(script.read())
    mat = robjects.r["still"]([0, 1, 2, 3, 4, 5], 3, 2)
    print(mat)

    # JavaScript

    asyncio.get_event_loop().run_until_complete(main())  # 调用js

    # julia
    jl = Julia(compiled_modules=False)
    jl.include("./src/julia/main.jl")  # 引用julia文件
    matrix = [[.2, .4, .1, .5, .2], [.1, .9, .1, .3, .3], [.2, .1, .1, .1, .4]]
    label = jl.eval("label")  # jl文件中的label函数
    res = label(matrix)  # 调用并返回
    print(res)

    # Java
    JVM_PATH = jpype.getDefaultJVMPath()

    dirs = os.path.join(os.path.abspath("./target/main.jar"))  # jar包目录
    print(dirs)
    jpype.startJVM(
        JVM_PATH,
        "-ea",
        "-Djava.class.path=" + dirs,
    )  # 启动jvm

    try:
        def encrypt(plaintext: str):
            package = jpype.JPackage("org.example.demo")  # 获取java包
            util_class = package.CryptoUtil  # 获取包里面的一个类
            key_pair = util_class.getKeyPair()  # 然后调用类里面的方法,因为是抽象类和静态方法,所以不用写util_class()实例化
            public_key = key_pair.getPublic()
            private_key = key_pair.getPrivate()
            ciphertext = util_class.encrypt(plaintext, public_key)
            res = util_class.decrypt(ciphertext, private_key)
            return ciphertext, res
        content = "content"
        ciphertext, plaintext = encrypt(plaintext=content)
        print("明文:", content)
        print("密文:", ciphertext)
        print("解密:", plaintext)
    except BaseException as e:
        print(e)
    try:
        jpype.shutdownJVM()  # 关闭后就不能继续使用java了
    except BaseException as e:
        print(e)

运行结果

encoding utf-8
Linux version 5.4.0-109-generic (buildd@ubuntu) (gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)) #123-Ubuntu SMP Fri Apr 8 09:10:54 UTC 2022
Linux Ubuntu 5.4.0-109-generic #123-Ubuntu SMP Fri Apr 8 09:10:54 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
Python 3.9.12
gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

R version 4.2.0 (2022-04-22) -- "Vigorous Calisthenics"
Copyright (C) 2022 The R Foundation for Statistical Computing
Platform: x86_64-conda-linux-gnu (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under the terms of the
GNU General Public License versions 2 or 3.
For more information about these matters see## 标题
https://www.gnu.org/licenses/.

julia version 1.6.6
openjdk 11.0.14.1 2022-02-08 LTS
OpenJDK Runtime Environment Microsoft-31205 (build 11.0.14.1+1-LTS)
OpenJDK 64-Bit Server VM Microsoft-31205 (build 11.0.14.1+1-LTS, mixed mode)
Shell script path: /home/nebula/Documents/projects/src/shell
Package               Version
--------------------- -----------
appdirs               1.4.4
certifi               2022.6.15
cffi                  1.15.1
importlib-metadata    4.12.0
Jinja2                3.1.2
JPype1                1.4.0
julia                 0.5.7
MarkupSafe            2.1.1
pip                   21.2.4
pycparser             2.21
pyee                  8.2.2
pyppeteer             1.0.2
pytz                  2022.1
pytz-deprecation-shim 0.1.0.post0
rpy2                  3.5.2
setuptools            61.2.0
tqdm                  4.64.0
tzdata                2022.1
tzlocal               4.2
urllib3               1.26.10
websockets            10.3
wheel                 0.37.1
zipp                  3.8.0
========分界线========
已添加清单
正在添加: org/(输入 = 0) (输出 = 0)(存储了 0%)
正在添加: org/example/(输入 = 0) (输出 = 0)(存储了 0%)
正在添加: org/example/demo/(输入 = 0) (输出 = 0)(存储了 0%)
正在添加: org/example/demo/CryptoUtil.class(输入 = 2423) (输出 = 1194)(压缩了 50%)
========分界线========
7PS : <ctypes.LP_c_char object at 0x7fe2c398fd40>
0
<class 'rpy2.robjects.vectors.ListVector'>
     [,1] [,2]
[1,] 0    3   
[2,] 1    4   
[3,] 2    5   

     [,1] [,2] [,3]
[1,] 0    1    2   
[2,] 3    4    5   


DevTools listening on ws://127.0.0.1:36341/devtools/browser/9e3f7896-6b49-4b37-ac43-bba660785b13
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.61 Safari/537.36


[104839:104839:0710/002805.987212:ERROR:shared_image_manager.cc(228)] SharedImageManager::ProduceSkia: Trying to Produce a Skia representation from a non-existent mailbox.
/home/nebula/.conda/envs/default/lib/python3.9/site-packages/julia/core.py:703: FutureWarning: Accessing `Julia().<name>` to obtain Julia objects is deprecated.  Use `from julia import Main; Main.<name>` or `jl = Julia(); jl.eval('<name>')`.
  warnings.warn(
[[0.0, 0.0, 0.0, 0.5, 0.0], [0.0, 0.9, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.4]]
/mnt/sda1/nebula/Documents/projects/target/main.jar
明文: content
密文: iI65ZjjYUQszfmUSA7nDYqo6tg1ywQvLV2nJIkbLJHi9118A21O9QnlaPut1wM2zNbud4VllKJEkheySQKalQa3mXKvJuW8nRABZncO9z8j2igW4E7yFNeCT0vXiZAV6iIeAi05SDL+i8VitKSKUiG3cIrlPV14IUm1XZWW4fNU=
解密: content
  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值