工控编程吧
标题: VS2019通过C语言直接调用PYTHON库 [打印本页]
作者: qq263946146    时间: 2021-6-1 13:33
标题: VS2019通过C语言直接调用PYTHON库
本想将写好的PYTHON文件打包成DLL供VS2019使用。
打包一下成众多文件,发再1个多GB,打包成独立exe文件也有400MB。
两行代码就这么大,看来也没啥意义再打包了。
python环境安装好了,就直接在本地用吧。
用vs2019直接调用python写好的py文件就好,也很方便。
这里记录下操作过程遇到的坑与解决方法。
也是第一次接触python,折腾的够呛。
首先也是自行安装VS2019,Anacoda3,pycharm.
我都是使用最新版本的64位。
可参考先前写的帖子。
https://www.gkbc8.com/forum.php?mod=viewthread&tid=15933
产生用pycharm或VS2019编写一个PY文件用于测试。
内容如下,涉及的第三方库都可以在Anacoda3里下载安装。
我这里是测试使用EASYOCR库。
主要是想通过VS2019直接调用下面的函数ocr。
- from gettext import gettext
 
- import easyocr
 
 
- # 结果为rect,文本,可信度 [([[189, 75], [469, 75], [469, 165], [189, 165]], '愚园路', 0.3754989504814148) ]
 
- # result = reader.readtext('d:/1.bmp')  #
 
- # 结果为简单的字符数组,如['愚园路', '西', '东', '315', '309', 'Yuyuan Rd.', 'W', 'E'];
 
 
- # result = reader.readtext('d:/1.bmp', detail=0, paragraph=True)
 
 
 
- # file = open('C:/Users/baikhgmv/Desktop/' + 'new' + '.txt', 'w')
 
- # file.close()
 
 
- # print(result)
 
- # gettext(message=1)
 
 
- reader = easyocr.Reader(['ch_sim', 'en'], gpu=False)  # 仅需初始化一次;
 
 
 
- def typeof(variate):
 
-     variate_type = None
 
-     if isinstance(variate, int):
 
-         variate_type = "int"
 
-     elif isinstance(variate, str):
 
-         variate_type = "str"
 
-     elif isinstance(variate, float):
 
-         variate_type = "float"
 
-     elif isinstance(variate, list):
 
-         variate_type = "list"
 
-     elif isinstance(variate, tuple):
 
-         variate_type = "tuple"
 
-     elif isinstance(variate, dict):
 
-         variate_type = "dict"
 
-     elif isinstance(variate, set):
 
-         variate_type = "set"
 
-     return variate_type
 
 
 
- def com(s):
 
-     print(s)
 
-     rst = '123'
 
-     return rst
 
 
 
- def ocr(filepath):
 
-     rst = reader.readtext(filepath, detail=0, paragraph=True)
 
-     print(typeof(rst))
 
-     print(rst)
 
-     return rst
 
新建一文件test.cpp。复制下面的内容,再设置路径。
- #include "stdio.h"
 
- #include "stdlib.h"
 
- //#include "detect_text.h"
 
- //#pragma comment(lib,"OCRDLL.lib")
 
 
- #include <string>
 
- #include <Python.h>
 
- #include<iostream>
 
- #include<Windows.h>
 
 
- using namespace std;
 
 
 
- wchar_t* utf_8ToUnicode(const char* u8s)
 
- {
 
-         int wcsLen = MultiByteToWideChar(CP_UTF8, NULL, u8s, (int)strlen(u8s), NULL, NULL)+1;
 
-         wchar_t* wcString = new wchar_t[wcsLen];
 
-         ZeroMemory(wcString, wcsLen);
 
-         MultiByteToWideChar(CP_UTF8, NULL, u8s, (int)strlen(u8s), wcString, wcsLen);
 
-         return wcString;
 
- }
 
- char* unicodeToAnsi(wchar_t* wcString)
 
- {
 
-         int len = WideCharToMultiByte(CP_ACP, NULL, wcString, -1, NULL, NULL, NULL, NULL)+1;
 
-         char* str = new char[len];
 
-         ZeroMemory(str, len);
 
-         WideCharToMultiByte(CP_ACP, NULL, wcString, -1, str, len, NULL, NULL);
 
-         return str;
 
- }
 
- int main()
 
- {
 
-         //<>初始化python模块
 
-         Py_SetPythonHome(L"D:\\ProgramData\\Anaconda3\\envs\\easyocr");
 
-         Py_Initialize(); 
 
-         if (!Py_IsInitialized())
 
-         {
 
-                 cout << "初始化失败" << endl;
 
-                 Py_Finalize();
 
-                 return 0;
 
-         }
 
 
-         PyRun_SimpleString("import sys");
 
-         PyRun_SimpleString("sys.path.append('./')");//设置python模块搜寻位置,文件放在.cpp文件一起
 
-         PyObject* pModule = NULL;
 
-         PyObject* pFunc   = NULL;
 
-         PyObject* pArg    = NULL;
 
-         pModule = PyImport_ImportModule("ocr");//Python文件名
 
-         if (!pModule) 
 
-         {
 
-                 cout << "py文件导入失败" << endl;
 
-         }
 
-         else
 
-         {
 
-                 pFunc = PyObject_GetAttrString(pModule, "ocr");//Python文件中的函数名  
 
-                 if (!pFunc) 
 
-                 {
 
-                         cout << "函数导入失败" << endl;
 
-                         Py_Finalize();
 
-                 }
 
-                 PyObject* pyParams = Py_BuildValue("(s)", "D:\\1.bmp");//c++类型转python类型
 
-                 pArg = PyEval_CallObject(pFunc, pyParams);//调用函数
 
-                 
 
-                 if (PyList_Check(pArg))
 
-                 {
 
-                         PyObject* list_item = NULL;
 
-                         char* pStr = NULL;//c类型的列表元素
 
-                         for (int sb=0; sb < PyObject_Size(pArg); sb++)
 
-                         {
 
-                                 //根据下标取出python列表中的元素,再转为字符串;
 
-                                 list_item = PyList_GetItem(pArg, sb);                                
 
-                                 PyArg_Parse(list_item, "s", &pStr);
 
-                                 
 
-                                 //python3默认为utf8编码,将其转为ansi,正常显示结果;
 
-                                 wchar_t* p = NULL;
 
-                                 char* p2 = NULL;
 
-                                 p  = utf_8ToUnicode(pStr);
 
-                                 p2 = unicodeToAnsi(p);
 
-                                 cout << p2 << "\r\n" << endl;
 
-                                 //
 
-                                 if (p)
 
-                                         delete[]p;
 
-                                 if (p2)
 
-                                         delete[]p2;
 
-                         }
 
-                 }
 
-         }
 
-         char a = getchar();
 
-         Py_Finalize();
 
-         return 0;
 
- }
头文件路径
D:\ProgramData\Anaconda3\envs\easyocr\include
库文件路径
D:\ProgramData\Anaconda3\envs\easyocr\libs
D:\ProgramData\Anaconda3为Anaconda3的安装位置,
我使用Anaconda3创建了一个新的环境easyocr,
所以使用此环境下的路径。
直接编译工程,正常生成exe程序。
将刚才的py文件复制一份到exe程序与test.cpp都一份。
一个是编译时会用到,一个是运行时会用到。
直接进行程序。
不出意外,会有如下提示错误。
mkl-service第三方库我在Anaconda3创建的环境easyocr里,是有安装的,
版本也是匹配的,最后大量查阅网络,是路径问题。
- D:\ProgramData\Anaconda3\envs\easyocr\lib\site-packages\numpy\__init__.py:138: UserWarning: mkl-service package failed to import, therefore Intel(R) MKL initialization ensuring its correct out-of-the box operation under condition when Gnu OpenMP had already been loaded by Python process is not assured. Please install mkl-service package, see http://github.com/IntelPython/mkl-service
 
-   from . import _distributor_init
 
- py文件导入失败
解决方法如下。
电脑系统环境变量Path添加python环境的三个路径。
如我的
系统环境设置,重启电脑
D:\ProgramData\Anaconda3\envs\easyocr
D:\ProgramData\Anaconda3\envs\easyocr\Scripts
D:\ProgramData\Anaconda3\envs\easyocr\Library\bin
测试后,反复测试还是不行。
直接放弃,关机睡觉。
第二天继续开机测试,一切OK了。
经过反复测试,确定了原因。
系统环境设置后,重启电脑才能正常,重要的事搞三遍。
系统环境设置,重启电脑
系统环境设置,重启电脑
系统环境设置,重启电脑
真恶心。
最后
在C++调用python库前还得Py_SetPythonHome。
调用函数设置
Py_SetPythonHome(L"D:\\ProgramData\\Anaconda3\\envs\\easyocr");
或也通过添加系统环境变量PYTHONHOME == D:\\ProgramData\\Anaconda3\\envs\\easyocr。
我已放弃折腾,在本地能用就好,也不在乎如何搞更加简便。
等后期有时间了,系统熟悉python编程。
好在python用的人多,遇到 的问题一搜都有答案,就是折腾人。
一切编译OK,运行程序。
效果如下
(, 下载次数: 15)