• C++ 将函数指针作为参数传递
    前言在C++中,你可以通过函数指针、函数对象(functor,即重载了operator()的类或者lambda表达式)或者std::function来传递函数作为参数。以下是这些方法的示例:1. 函数指针首先,你需要定义一个函数,然后你可以创建一个指向这个函数的指针,并将这个指针作为参数传递给另一个函数。#include <iostream> // 定义一个函数 void printHello() { std::cout << "Hello, World!" << std::endl; } // 定义一个接受函数指针作为参数的函数 void callFunction(void (*func)()) { func(); } int main() { callFunction(printHello); // 传递函数名,它会被隐式转换为函数指针 return 0; }2. 函数对象(也称为仿函数或functor)函数对象是一个重载了operator()的类实例,它可以像函数一样被调用。#include <iostream> // 定义一个函数对象 class PrintHello { public: void operator()() const { std::cout << "Hello, World!" << std::endl; } }; // 定义一个接受函数对象作为参数的函数 void callObject(const PrintHello& obj) { obj(); // 调用函数对象 } int main() { PrintHello hello; callObject(hello); // 传递函数对象实例 return 0; }3. std::functionstd::function是一个通用、多态的函数封装器。它允许你存储、复制和调用任何可调用的目标——函数、lambda表达式、bind表达式或其他函数对象,只要它们的签名兼容。#include <iostream> #include <functional> // 定义一个简单的函数 void printHello() { std::cout << "Hello, World!" << std::endl; } // 定义一个接受std::function作为参数的函数 void callFunction(const std::function<void()>& func) { func(); } int main() { // 直接传递函数 callFunction(printHello); // 使用lambda表达式 callFunction([]() { std::cout << "Hello from lambda!" << std::endl; }); return 0; }在上面的例子中,std::function<void()>是一个类型,它表示接受没有参数并返回void的可调用对象。你可以使用任何与这个签名兼容的可调用对象来创建std::function的实例,并传递给callFunction函数。
  • [技术干货] C++ 调用C#的DLL
    理论知识在C++中直接调用C#并传递String^(这看起来像是C++/CLI中的托管字符串类型)和C#对象是比较复杂的,因为C++和C#是两种不同的编程语言,运行在不同的运行时环境中。但是,你可以通过几种方法来实现这种交互:使用C++/CLI作为桥梁: 你可以使用C++/CLI来编写一个包装器类,该类可以在C++和C#之间传递数据。C++/CLI允许你在C++代码中使用.NET类型,并可以很容易地与C#代码交互。**使用P/Invoke或C++/CX (COM)**: 如果你的C#代码暴露为COM组件或DLL(使用C++/CX或P/Invoke),则可以从C++代码中调用它。但是,这通常不直接支持传递C#对象;你可能需要将这些对象序列化为字节数组或其他可以在两种语言之间传递的类型。**使用IPC (进程间通信)**: 你可以使用命名管道、WCF、TCP/IP套接字或其他IPC机制在C++和C#进程之间传递数据。这允许你在两个独立的进程中进行通信,每个进程都可以使用它自己的语言运行时。使用C#的DLLImport: 如果你的C++代码是编译为DLL的,并且你希望从C#中调用它,你可以使用C#的DllImport属性来导入C++函数。但是,这通常只适用于简单的C函数,而不是C++类或对象。对于你的情况,一个使用C++/CLI作为桥梁的简单示例可能如下所示:代码实战C#代码 (YourCSharpLibrary.dll)public class YourCSharpClass { public string YourMethod(string input) { // ... 处理输入并返回结果 ... return "Processed: " + input; } }C++/CLI代码 (YourBridge.dll)// YourBridge.cpp #include "YourBridge.h" #using "YourCSharpLibrary.dll" as_friend YourCSharpClass^ CreateCSharpObject() { return gcnew YourCSharpClass(); } String^ CallCSharpMethod(YourCSharpClass^ obj, String^ input) { return obj->YourMethod(input); }C++代码 (调用C++/CLI)// YourNativeCppCode.cpp #include <iostream> #include <msclr/marshal_cppstd.h> // 用于字符串转换(如果需要) #using "YourBridge.dll" int main() { YourCSharpClass^ obj = CreateCSharpObject(); String^ csharpString = gcnew String("Hello from C++"); String^ result = CallCSharpMethod(obj, csharpString); // 如果需要,将String^转换为std::string msclr::auto_gcroot<System::String^> resultWrapped(result); std::string stdResult = msclr::interop::marshal_as<std::string>(resultWrapped); std::cout << "Result from C#: " << stdResult << std::endl; return 0; }请注意,这个示例假设你已经有了C#库(YourCSharpLibrary.dll)和C++/CLI桥接库(YourBridge.dll)。C++/CLI桥接库负责在C++和C#之间转换和管理对象。在C++代码中,你通过C++/CLI桥接库来创建C#对象、调用C#方法,并在需要时转换数据类型。注意C# 是托管对象,C++ 是非托管对象,在参数传递的时候有很多限制。例如,不能把C#的托管对象传给C++的线程,这点一定要注意甄别
  • [技术干货] C++ 在类中创建并使用线程
    thread库在C++中,你可以使用<thread>库来在类中创建线程。然而,直接在类的成员函数中启动线程可能不是一个好主意,因为线程的生命周期和对象的生命周期可能会变得难以管理。但你可以通过在类的成员函数或成员变量中封装线程创建的逻辑来实现这一功能。简单线程示例以下是一个简单的示例,展示了如何在C++类的成员函数中启动一个线程:#include <iostream> #include <thread> #include <chrono> class MyClass { public: MyClass() : threadPtr(nullptr) {} // 启动线程的成员函数 void startThread() { // 检查线程是否已经在运行 if (threadPtr == nullptr) { // 使用lambda表达式捕获this指针,以便在线程中访问类的成员 threadPtr = std::make_unique<std::thread>([this]() { this->runInThread(); }); } else { std::cout << "Thread is already running!" << std::endl; } } // 线程执行的函数 void runInThread() { for (int i = 0; i < 5; ++i) { std::cout << "Running in thread: " << i << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); } } // 等待线程完成 void joinThread() { if (threadPtr != nullptr && threadPtr->joinable()) { threadPtr->join(); threadPtr.reset(); // 释放线程对象 } } private: std::unique_ptr<std::thread> threadPtr; // 使用unique_ptr管理线程对象的生命周期 }; int main() { MyClass obj; obj.startThread(); // 启动线程 // 让主线程等待一段时间,以便观察子线程的输出 std::this_thread::sleep_for(std::chrono::seconds(6)); obj.joinThread(); // 等待线程完成 return 0; }在这个示例中,MyClass类有一个成员变量threadPtr,它是一个std::unique_ptr<std::thread>类型,用于管理线程对象的生命周期。startThread成员函数检查线程是否已经在运行,如果没有,则创建一个新线程来执行runInThread成员函数。joinThread成员函数用于等待线程完成并释放线程对象。注意,在捕获this指针时要小心,因为如果对象在线程执行期间被销毁,这可能会导致未定义的行为。在这个示例中,我们通过使用std::unique_ptr来确保线程对象在线程完成后被正确销毁。线程传参如果你需要在startThread函数中传递一些参数到线程执行的函数中,你可以通过几种方式来实现。以下是一个示例,展示了如何使用std::bind或lambda表达式来传递参数:使用std::bind#include <iostream> #include <thread> #include <chrono> #include <functional> class MyClass { public: MyClass() : threadPtr(nullptr) {} // 启动线程的成员函数,接受一个int参数 void startThread(int param) { // 检查线程是否已经在运行 if (threadPtr == nullptr) { // 使用std::bind将参数绑定到成员函数上 threadPtr = std::make_unique<std::thread>(std::bind(&MyClass::runInThread, this, param)); } else { std::cout << "Thread is already running!" << std::endl; } } // 线程执行的函数,接受一个int参数 void runInThread(int param) { for (int i = 0; i < 5; ++i) { std::cout << "Running in thread with param: " << param << ", count: " << i << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); } } // 等待线程完成 void joinThread() { if (threadPtr != nullptr && threadPtr->joinable()) { threadPtr->join(); threadPtr.reset(); // 释放线程对象 } } private: std::unique_ptr<std::thread> threadPtr; // 使用unique_ptr管理线程对象的生命周期 }; int main() { MyClass obj; obj.startThread(42); // 启动线程并传递参数42 // 让主线程等待一段时间,以便观察子线程的输出 std::this_thread::sleep_for(std::chrono::seconds(6)); obj.joinThread(); // 等待线程完成 return 0; }使用Lambda表达式// ... 省略其他部分 ... void startThread(int param) { // 检查线程是否已经在运行 if (threadPtr == nullptr) { // 使用lambda表达式捕获this指针和param参数 threadPtr = std::make_unique<std::thread>([this, param]() { this->runInThread(param); }); } else { std::cout << "Thread is already running!" << std::endl; } } // ... 省略其他部分 ... int main() { MyClass obj; obj.startThread(42); // 启动线程并传递参数42 // ... 省略其他部分 ... }在这两个示例中,我们都修改了startThread函数以接受一个int参数,并将该参数传递给线程执行的函数runInThread。在第一个示例中,我们使用std::bind来绑定参数和成员函数,而在第二个示例中,我们使用lambda表达式来捕获参数并调用成员函数。两种方法都可以实现相同的效果。
  • [问题求助] 【MDC300】在mini0上运行编译生成文件报错
    运行了MDC300sample-1.0.107.2中的Ascendcl_sample,模型推理和编译都没有问题,把最终生成的编译文件bin,模型文件model,图片image发到mini上面运行,结果报错。
  • [问题求助] iot studio软件按照步骤安装,编译显示Arm-none-eabi-gcc:致命错误:没有输入文件编译终止。
    iot studio软件按照步骤安装,编译显示Arm-none-eabi-gcc:致命错误:没有输入文件编译终止。
  • [常见FAQ] 选手程序输出异常
    本地和判题器交互正常,有最终得分。但是线上提交显示:选手程序输出异常。
  • [问题求助] atlas 300,在开发环境中(x86),安装样例中samples/cplusplus/common/acllite库时,make报错
    报错如下:/usr/bin/ld: cannot find -lavdevice /usr/bin/ld: cannot find -lavfilter collect2: error: ld returned 1 exit status make: *** [out/x86_64/libacllite.so] Error 1 在路径下THIRDPART_PATH,目前只有安装好的ffmpeg包,/usr/local/Ascend/thirdpart/aarch64/ffmpeg/环境变量如下:开发端--x86export INSTALL_DIR=/usr/local/Ascend/ascend-toolkit/latest export INSTALL_DIR_ARM=/usr/local/Ascend/ascend-toolkit/ascend-toolkit_arm/latest/aarch64-linux export PATH=$PATH:/usr/local/bin/cmake:${INSTALL_DIR}/atc/ccec_compiler/bin:${INSTALL_DIR}/atc/bin:${INSTALL_DIR}/bin:${INSTALL_DIR}/compiler/ccec_compiler/bin export LD_LIBRARY_PATH=${INSTALL_DIR}/acllib/lib64:${INSTALL_DIR}/atc/lib64:/usr/local/Ascend/ascend-toolkit/6.3.RC1.alpha001/runtime/lib64/stub:$LD_LIBRARY_PATH export ASCEND_OPP_PATH=${INSTALL_DIR}/opp export ASCEND_AICPU_PATH=/usr/local/Ascend/ascend-toolkit/latest/aarch64-linux export PYTHONPATH=${INSTALL_DIR}/atc/python/site-packages:${INSTALL_DIR}/opp/built-in/op_impl/ai_core/tbe:$PYTHONPATH export TOOLCHAIN_HOME=${INSTALL_DIR}/toolkit export ASCEND_HOME_PATH=${INSTALL_DIR} export DDK_PATH=/usr/local/Ascend/ascend-toolkit/latest/arm64-linux export NPU_HOST_LIB=${DDK_PATH}/runtime/lib64/stub export CPU_ARCH=`arch` export THIRDPART_PATH=/usr/local/Ascend/thirdpart/${CPU_ARCH} 
  • [问题求助] 在arm中,将数据写入device时,报错malloc device data buffer failed, aclRet is 107002
    报错代码如下:void* AtlasEngine::CopyDataToDevice(void* data, uint32_t dataSize, aclrtMemcpyKind policy) {    void* buffer = nullptr;    aclError aclRet = aclrtMalloc(&buffer, dataSize, ACL_MEM_MALLOC_HUGE_FIRST);    if (aclRet != ACL_SUCCESS) {        ERROR_LOG("malloc device data buffer failed, aclRet is %d", aclRet);        return nullptr;    }根据错误码,也检查了context,返回的是create context success,是创建成功的;aclrtSetDevice(deviceId_);也是成功的, ret = aclrtCreateContext(&context_, deviceId_);    if (ret != ACL_SUCCESS) {        ERROR_LOG("acl create context failed, deviceId = %d, errorCode = %d",            deviceId_, static_cast<int32_t>(ret));        return FAILED;    }    INFO_LOG("create context success");
  • [技术干货] 64位MFC调用32位DLL
    当64位MFC应用程序调用32位DLL时,你可以通过创建一个中间层Wrapper DLL来实现。下面是一个简单的示例,演示如何从64位MFC应用程序调用32位DLL的函数:假设你有一个32位DLL,其中包含一个名为MyFunction的函数,它接受一个整数参数并返回一个整数。你想从64位MFC应用程序中调用这个函数。首先,创建一个新的64位DLL项目(Wrapper DLL),用于与32位DLL进行交互。在这个64位DLL项目中,编写一个导出函数,该函数将调用32位DLL的函数。下面是一个简单的例子:// WrapperDLL.h #pragma once #ifdef WRAPPERDLL_EXPORTS #define WRAPPERDLL_API __declspec(dllexport) #else #define WRAPPERDLL_API __declspec(dllimport) #endif extern "C" WRAPPERDLL_API int CallMyFunction(int value);// WrapperDLL.cpp #include "WrapperDLL.h" #include "windows.h" typedef int(*MYFUNCTION)(int); int CallMyFunction(int value) { HINSTANCE hDLL = LoadLibrary(L"path_to_32bit_dll.dll"); if (hDLL != NULL) { MYFUNCTION myFunction = (MYFUNCTION)GetProcAddress(hDLL, "MyFunction"); if (myFunction != NULL) { int result = myFunction(value); FreeLibrary(hDLL); return result; } FreeLibrary(hDLL); } return -1; }在这个示例中,我们创建了一个名为CallMyFunction的导出函数。该函数加载32位DLL,并使用GetProcAddress函数获取MyFunction函数的地址。然后,我们将参数传递给32位DLL的函数,并返回结果。接下来,编译这个Wrapper DLL项目,并生成一个64位的DLL文件。然后,在你的64位MFC应用程序中,你可以通过调用CallMyFunction函数来间接调用32位DLL的函数。例如:// MFCAppDlg.cpp (64位MFC应用程序的对话框类文件) #include "WrapperDLL.h" // ... void CMFCAppDlg::OnBnClickedButton1() { int result = CallMyFunction(42); // 处理结果... }这里,我们在MFC应用程序中的按钮单击事件处理程序中调用了CallMyFunction函数,将参数值 42 传递给32位DLL的函数。你可以根据需要使用返回的结果。需要确保在编译64位MFC应用程序和Wrapper DLL时,使用相应的64位编译器选项。此外,还需要将32位DLL的路径替换为你自己的实际路径。这只是一个简单的示例,具体的实现可能因实际情况而有所不同。你可能需要根据32位DLL的特定函数和参数来进行更多的调整和适配。
  • [常见FAQ] C++如何Debug
    文档里说的调试器太简单了   能细说吗?解锁新知识
  • [问题求助] 按照样例操作,执行bash sample_build.sh的时候,编译出错,新人求指导
    正在学习Atlas 200 DK,用了分设环境,CANN是6.0.RC1,固件与驱动版本是1.0.13.alpha,目前卡在开发环境,试了两个C++的检测样例,都是成功模型转换,但在运行提供的bash sample_build.sh编译的时候,都报同样的错,想请教一下有经验的大佬
  • [开发资源] Restful 接口API开发文档
    使用restful接口进行对接和开发时,可以参考附件文档中的说明进行开发20221019:更新最新版本(10-10号发布)
  • [问题求助] 请求文档链接
    请问谁有《IPC V200R003C00 智能元数据结构设计说明书》?谢谢!
  • [问题求助] 捉虫,输入0D/1DTensor,1D张量时shape为1,获取不到(或不正确)获取那唯一元素的值,后来分int64,int32尝试获取了也不行
    固定值的Tensor输入可行,这两种用例随机范围0-10输入,不行原因设备日志显示,在于超时​UT增加用例input_int64_data_type_float,input_int64_data_type_default会有出现过超时bad_alloc,或段错误(调试时是获取不正确,n过大如下):@莫晓忧,有空麻烦上仓帮忙看一下实现和用例两个文件。感谢涛哥和各位版主了!尝试了memcpy_s,5个输入int64ut用例失败。但改上面两个随机Tensor用例为Int32输入,这两个随机x输入用例st设备本地测试也不通过,所以应该只能是cann仓的问题
  • [API使用] 请问想在Qt项目中使用mindspore lite进行推理有没有示例可以参考?
    如题,想在自己的Qt项目中加入mindspore lite的API进行推理,有没有什么示例可以参考?
总条数:310 到第
上滑加载中