学习Linux/GNU/C++/C过程中遇到的问题
- 1.源函数调用:
- 2.linux静态库使用:
- 3.vscode创建c++程序调用onnxruntime:
- 问题1:找不到头文件或者未定义函数
- 问题2:error while loading shared libraries: libonnxruntime.so.1.16.1: cannot open shared object file: No such file or directory
- 典型使用demo:
- 4. c++调用c源程序注意及c/c++区别:
- 1.c及c++函数签名不同:c++为了函数重载,同一函数签名根据参数不同而不同:
1.源函数调用:
c++文件调用另一个cpp文件:函数声明在libtest.h中,函数定义在libtest.cpp中,则test.cpp调用libtest.h中声明的函数时,使用#include "libtest.cpp"而不是“libtest.h”,否则出现函数未调用。c++调用c文件则include xxx.h头文件。
2.linux静态库使用:
g++ -c libtest.cpp -o libtest.o编译源文件为目标文件.o
ar rcs libtest.a libtest.o由.o目标文件生成静态库
g++ test.cpp -o test -static -L.编译test.cpp,在test.cpp中include"libtest.cpp",-static指示使用静态链接,-L.指示在当前文件夹查找所需库文件,在-L.后加上 -lerr则便是在当前命令下查找库文件liberr,可使用file test查看是否成功静态链接
运行./test可执行文件
3.vscode创建c++程序调用onnxruntime:
问题1:找不到头文件或者未定义函数
解决1:在task.json文件的args部分加上:
"-I/tao/code/package/onnxruntime/include",//大写I表示include目录
"-L/tao/code/package/onnxruntime/lib",//大写L表示.so共享库目录
"-lonnxruntime",//小写l为lib库名称,库目录中文件全名为libonnxruntime.so,这里用l来表示lib
最后:注意task或c_cpp_properties.json中编译器命令是否为g++,不用gcc;
问题2:error while loading shared libraries: libonnxruntime.so.1.16.1: cannot open shared object file: No such file or directory
解决2:tasks.json内指定库目录即名称任然报错,因为默认情况下,编译器只会使用/lib和/usr/lib这两个目录下的库文件.
通常通过源码包进行安装时,如果不指定–prefix,提示找不到相关的.so库,会报错。也就是说,.so文件目录不在系统默认的库搜索目录中,需要将目录加进去.
配置文件在:/etc/ld.so.conf文件中,将所在的库目录加入到共享库的配置文件中:执行vi /etc/ld.so.conf,在"include ld.so.conf.d/*.conf"下方增加/tao/code/package/onnxruntime/lib。
保存后,在命令行终端执行:/sbin/ldconfig -v和ldconfig.
其作用是将文件/etc/ld.so.conf列出的路径下的库文件缓存到/etc/ld.so.cache以供使用.
因此当安装完一些库文件,或者修改/etc/ld.so.conf增加了库的新搜索路径,需要运行一下ldconfig,
使所有的库文件都被缓存到文件/etc/ld.so.cache中,如果没做,可能会找不到刚安装的库。
典型使用demo:
#include <onnxruntime_cxx_api.h>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <iomanip>
//#pragma comment(lib, "user32.lib")
//#pragma comment(lib, "gdi32.lib")
//#pragma comment(lib, "onnxruntime.lib")
template <typename T>
static void softmax(T& input) {
float rowmax = *std::max_element(input.begin(), input.end());
std::vector<float> y(input.size());
float sum = 0.0f;
for (size_t i = 0; i != input.size(); ++i) {
sum += y[i] = std::exp(input[i] - rowmax);
}
for (size_t i = 0; i != input.size(); ++i) {
input[i] = y[i] / sum;
}
}
// This is the structure to interface with the MNIST model
// After instantiation, set the input_image_ data to be the 28x28 pixel image of the number to recognize
// Then call Run() to fill in the results_ data with the probabilities of each
// result_ holds the index with highest probability (aka the number the model thinks is in the image)
struct MNIST {
MNIST() {
auto memory_info = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);
input_tensor_ = Ort::Value::CreateTensor<float>(memory_info, input_image_.data(), input_image_.size(),input_shape_.data(), input_shape_.size());
output_tensor_ = Ort::Value::CreateTensor<float>(memory_info, results_.data(), results_.size(),output_shape_.data(), output_shape_.size());
}
std::ptrdiff_t Run() {
const char* input_names[] = { "Input3" };
const char* output_names[] = { "Plus214_Output_0" };
Ort::RunOptions run_options;
session_.Run(run_options, input_names, &input_tensor_, 1, output_names, &output_tensor_, 1);
softmax(results_);
result_ = std::distance(results_.begin(), std::max_element(results_.begin(), results_.end()));
return result_;
}
static constexpr const int width_ = 28;
static constexpr const int height_ = 28;
std::array<float, width_* height_> sneakers = { 0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0039,0.0078,0.0000,0.0000,0.0000,0.0000,0.0000,0.2431,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0431,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.5725,0.6902,0.4510,0.7137,0.1137,0.0000,0.0000,0.0000,0.0157,0.0000,0.0000,0.4588,0.7922,0.0471,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0078,0.0039,0.0000,0.0000,0.0000,0.1333,0.9255,0.5765,0.4941,0.4392,0.6392,0.6902,0.0000,0.0000,0.0000,0.0000,0.0000,0.3647,0.8000,0.8510,0.2039,0.0000,0.0000,0.0000,0.0039,0.0000,0.0039,0.0000,0.0000,0.0000,0.0235,0.1176,0.9255,0.4902,0.4627,0.2824,0.4078,0.4510,0.4784,0.7451,0.9333,0.4588,0.1451,0.1255,0.3569,0.7804,0.7843,0.6667,0.0980,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.2392,0.2392,0.7412,0.6392,0.3137,0.3216,0.4314,0.4941,0.4941,0.5294,0.5333,0.4510,0.6863,0.8667,0.8392,0.7922,0.8667,0.7529,0.5294,0.7412,0.1529,0.0000,0.0000,0.0000,0.0000,0.0000,0.1412,0.2039,0.5843,0.7412,0.2549,0.2980,0.3922,0.4353,0.4510,0.4627,0.4745,0.5020,0.5333,0.4784,0.3529,0.3804,0.5333,0.6706,0.6745,0.4118,0.3529,0.8667,0.1294,0.1451,0.4902,0.4039,0.4353,0.4863,0.5059,0.4353,0.3333,0.3804,0.4667,0.4588,0.4039,0.4196,0.4471,0.5333,0.6275,0.6745,0.7098,0.7373,0.7725,0.7294,0.5765,0.4353,0.3686,0.4392,0.6667,0.7961,0.2980,0.5569,0.7373,0.7098,0.7098,0.6980,0.6392,0.5882,0.4941,0.4078,0.4196,0.5490,0.6314,0.7373,0.8000,0.8353,0.8667,0.8824,0.8824,0.8549,0.8196,0.5725,0.7804,1.0000,0.9882,0.8235,0.8196,0.8078,0.1569,0.2275,0.4863,0.6000,0.6667,0.7176,0.7373,0.6824,0.7137,0.6549,0.7843,0.8275,0.8118,0.8000,0.7412,0.7647,0.5843,0.3333,0.4078,0.7294,0.0000,0.0000,0.0000,0.0510,0.0902,0.0902,0.0471,0.0235,0.0706,0.0588,0.1059,0.0078,0.0078,0.0196,0.0510,0.1843,0.2706,0.5569,0.2784,0.0980,0.0235,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.1059,0.2824,0.0980,0.0902,0.0784,0.0431,0.0471,0.0902,0.1451,0.1843,0.0000,0.1137,0.2706,0.2863,0.2667,0.2039,0.0314,0.2235,0.1333,0.0000,0.0235,0.1020,0.1529,0.1529,0.1882,0.2235,0.2275,0.2118,0.1059,0.2549,0.3373,0.1529,0.1725,0.1608,0.1686,0.2118,0.2588,0.1843,0.0000,0.0000,0.0000,0.0000,0.1412,0.1765,0.1765,0.2863,0.2157,0.2863,0.3137,0.2588,0.2392,0.2314,0.1882,0.1529,0.1686,0.1765,0.2000,0.1725,0.2314,0.1608,0.1765,0.2275,0.2275,0.1765,0.1412,0.0039,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000
};
std::array<float, width_* height_> input_image_ = sneakers;
std::array<float, 10> results_{};
int64_t result_{ 0 };
private:
Ort::Env env;
Ort::Session session_{ env, "mnist.onnx", Ort::SessionOptions{nullptr} };
Ort::Value input_tensor_{ nullptr };
std::array<int64_t, 4> input_shape_{ 1, 1, width_, height_ };
Ort::Value output_tensor_{ nullptr };
std::array<int64_t, 2> output_shape_{ 1, 10 };
};
using namespace std;
int main(void)
{
char* labellist[10] = { "T - shirt" ," pants "," pullover","qunzhi"," coat"," sandals "," shirt","yundongxie","bag","ankle boots" };
struct MNIST *mnist = new MNIST();
mnist->Run();
cout << setiosflags(ios::fixed)<<setprecision(5);
std::cout << "result0:" << mnist->results_[0]<<endl;
std::cout << "result1:" << mnist->results_[1] << endl;
std::cout << "result2:" << mnist->results_[2] << endl;
std::cout << "result3:" << mnist->results_[3] << endl;
std::cout << "result4:" << mnist->results_[4] << endl;
std::cout << "result5:" << mnist->results_[5] << endl;
std::cout << "result6:" << mnist->results_[6] << endl;
std::cout << "result7:" << mnist->results_[7] << endl;
std::cout << "result8:" << mnist->results_[8] << endl;
std::cout << "result9:" << mnist->results_[9] << endl;
std::cout << "over" << endl;
cout << "the result: " << mnist->result_ << endl;
cout << "the result: " << labellist[mnist->result_] << endl;
return 0;
4. c++调用c源程序注意及c/c++区别:
1.c及c++函数签名不同:c++为了函数重载,同一函数签名根据参数不同而不同:
//libtest.c文件
#include <stdio.h>
#include "libtest.h"
int area(int x,int y)
{
return x*y;
}
使用gcc -c libtest.c -o libtest.o生成目标文件后使用objdump -t libtest.o查看函数签名:
//libtest.cpp
#include <iostream>
#include "libtest.h"
using namespace std;
int area(int x,int y)
{
cout<<"result";
return x*y;
}
使用g++ -c libtest.cpp -o libtest.o生成目标文件,再使用objdump -t libtest.o查看,结果如下图。
可看到函数area的数字签名为Z4areaii,其中ii表示两个int类型的参数,如果是double的则是d。以此区别函数重载的各个函数。
因此cpp程序不能直接调用c程序,否则出现函数未定义。
如要在cpp中调用c程序,则在.h文件中使用extern “C”,对应的.c文件不变,如图:最开始#ifdef判断是否是g++编译器,因为c++编译器默认定义了__cplusplus符号,extern "C“指示c++编译器按c的方式生成函数签名,extern "C”不能被c编译器编译,所以用#ifdef判断。libtest.c和libtest.h如下所示:
gcc -c libtest.c -o libtest.o生成目标文件
ar cr -o libtest.a libtest.o生成静态库
gcc -o main main.cpp -L. -ltest -lstdc++//main.cpp会用libtest.a静态库,因为使用的gcc编译器c++,因此指明使用stdc++库
./main即可正常运行
使用 ldd main可查看对应的库:stdc++,使用g++编译c++程序会自动指明使用该库,使用gcc则单独指明-lstdc++
即gcc -c libtest.cpp -o libtest.o -lstdc++