要实现UE4C++到第三方库的调用,需要自己在自己创建的插件库里的\Source路径下创建一个目录为ThirdParty的文件夹在里面放入你需要放入的第三方库
当你放入了第三方库的文件之后,需要自己写一个cs文件,用于UE4自己添加lib和include
然后需要在cs填写库的运用
using UnrealBuildTool; public class PythonThirdParty : ModuleRules { public PythonThirdParty(ReadOnlyTargetRules Target) : base(Target) { //python版本 //string PythonThirdPartyValue = "2.7"; //表示第三方库 Type= ModuleType.External; //第三方库新模块根目录目录路径 //string RootPath = Target.UEThirdPartySourceDirectory + "PythonThirdParty/"; //包含的头文件路径,因为编译的库里面都是链接过的编译单元,可以认为编译单元是不包含头文件的,所以在之后的使用时还需要获取到头文件的声明信息 PublicIncludePaths.Add(ModuleDirectory + "/include/"); if(Target.Platform == UnrealTargetPlatform.Win32 || Target.Platform == UnrealTargetPlatform.Win64) { //第三方静态库的路径 PublicLibraryPaths.Add(ModuleDirectory + "/libs/"); //第三方静态库的名称 PublicAdditionalLibraries.Add("python27.lib"); PublicAdditionalLibraries.Add("_bsddb.lib"); PublicAdditionalLibraries.Add("_ctypes.lib"); PublicAdditionalLibraries.Add("_elementtree.lib"); PublicAdditionalLibraries.Add("_hashlib.lib"); PublicAdditionalLibraries.Add("_msi.lib"); PublicAdditionalLibraries.Add("_multiprocessing.lib"); PublicAdditionalLibraries.Add("_socket.lib"); PublicAdditionalLibraries.Add("_sqlite3.lib"); PublicAdditionalLibraries.Add("_ssl.lib"); PublicAdditionalLibraries.Add("_testcapi.lib"); PublicAdditionalLibraries.Add("_tkinter.lib"); PublicAdditionalLibraries.Add("bz2.lib"); PublicAdditionalLibraries.Add("pyexpat.lib"); PublicAdditionalLibraries.Add("select.lib"); PublicAdditionalLibraries.Add("unicodedata.lib"); PublicAdditionalLibraries.Add("winsound.lib"); } } }
这样我们就能在UE4插件的cs文件里面添加自身命名的第三方库名称(cs文件的命名)
现在我们就可以使用python这个第三方库了,现在我们需要使用C++来调用python,首先我们需要把python文件的东西整理成一个函数
import requests import os def OutBaiduAPILngAndLat(url,ak,path,origin,destination): #url = 'http://api.map.baidu.com/direction/v2/riding?' params = { 'ak':ak, 'origin':origin, 'destination':destination } r = requests.get(url,params) r_js = r.json() routes_ = r_js['result']['routes'][0] dis_ = routes_['distance'] time_ = routes_['duration'] f_path = path f_re = open(f_path,'w') with open(f_path,'r+') as f: read_data = f.read() f.seek(0) f.truncate() f.write(read_data.replace('apple','android')) steps_ = routes_['steps'] f_re.writelines(['Start','\n']) for step in steps_: path_ = step['path'] point_lst = path_.split(';') f_re.writelines(['------','\n']) for point in point_lst: lng = point.split(',')[0] lat = point.split(',')[1] f_re.writelines([str(lng),',',str(lat),'\n']) f_re.writelines(['End','\n']) f_re.writelines(['time:',str(time_),'\n']) f_re.writelines(['distance:',str(dis_),'\n']) f_re.close()
我设置的函数名为OutBaiduAPILngAndLat,需要C++传入的参数有五个,所以我们需要在C++里定义五个参数,方法为:
// 方法一:设置参数 或使用 /* PyObject* args = PyTuple_New(2); // 2个参数 PyObject* arg1 = PyUnicodeUCS2_FromString(Origin); // 参数一 PyObject* arg2 = PyUnicodeUCS2_FromString(Destination); // 参数二 PyTuple_SetItem(args, 0, arg1); PyTuple_SetItem(args, 1, arg2); */ // 方法二 PyObject* args = Py_BuildValue("(sssss)", API, s.c_str(), textPath.c_str(), Origin, Destination); // 调用函数 PyObject* pRet = PyObject_CallObject(pv, args);
完整代码:
// 调用Python Py_Initialize(); // FPaths::ProjectPluginsDir():获取UE4插件文件夹的路径 // Path:自身python文件目录位置 std::string chdir_cmd = std::string("sys.path.append(\"") + TCHAR_TO_UTF8(*FPaths::ProjectPluginsDir()) + Path + "\")"; const char* cstr_cmd = chdir_cmd.c_str(); PyRun_SimpleString("import sys"); //python定义到自身写的python文件目录 PyRun_SimpleString(cstr_cmd); // 加载自己python文件 PyObject* moduleName = PyString_FromString(Type); PyObject* pModule = PyImport_Import(moduleName); if (!pModule) // 加载模块失败 { UE_LOG(LogTemp, Warning, TEXT("[ERROR] Python get module failed.")); return; } // 加载函数 PyObject* pv = PyObject_GetAttrString(pModule, "OutBaiduAPILngAndLat"); if (!pv || !PyCallable_Check(pv)) // 验证是否加载成功 { UE_LOG(LogTemp, Warning, TEXT("[ERROR] Can't find funftion (OutBaiduAPILngAndLat)")); return ; } // 插件目录绝对位置 FString UE4Path = FPaths::ConvertRelativePathToFull(FPaths::ProjectPluginsDir()); FString UE4TextPath; TArrayUE4PathArray = UE4Path.GetCharArray(); for (auto & Item : UE4PathArray) { FString A; if (FString(1,&Item).Equals("/")) { A = "\\"; } else { A = FString(1, &Item); } UE4TextPath += A; } std::string textPath = TCHAR_TO_UTF8(*UE4TextPath) + std::string("PythonPlugins\\Source\\ThirdParty\\PythonThirdParty\\Resources\\walking.txt"); std::string file = TCHAR_TO_UTF8(*FPaths::ProjectPluginsDir()) + std::string("PythonPlugins/Source/ThirdParty/PythonThirdParty/Resources/MyBaiDuAk.txt"); std::ifstream infile; infile.open(file.data()); //将文件流对象与文件连接起来 std::string s; getline(infile, s); // 方法一:设置参数 或使用 /* PyObject* args = PyTuple_New(2); // 2个参数 PyObject* arg1 = PyUnicodeUCS2_FromString(Origin); // 参数一 PyObject* arg2 = PyUnicodeUCS2_FromString(Destination); // 参数二 PyTuple_SetItem(args, 0, arg1); PyTuple_SetItem(args, 1, arg2); */ // 方法二 PyObject* args = Py_BuildValue("(sssss)", API, s.c_str(), textPath.c_str(), Origin, Destination); // 调用函数 PyObject* pRet = PyObject_CallObject(pv, args); Py_Finalize(); //释放资源
如果需要看项目完整代码可以查看github:https://github.com/a948022284/UE4RealRoadPlanning