【问题标题】:Linking my Dynamic Link Library to my CPP executable将我的动态链接库链接到我的 CPP 可执行文件
【发布时间】:2021-05-22 16:07:20
【问题描述】:

我正在使用 CLion 和 cmake。

我想在cmakelists.txt 中将我的 dll 链接到我的 c++ 项目,但我不知道该怎么做。

我搜索了很多,但没有找到任何解决方案。


  1. 我已经在 c++ 中通过 Visual Studio 发布了一个 dll,我想将它链接到我的 cmake 项目。
    • 项目名称和输出名称为Benchmark -> Benchmark.dll

这里是代码:module.hpp

#pragma once
#ifdef CFAMILY_EXPORTS
#define CFAMILY_API __declspec(dllexport)
#else
#define CFAMILY_API __declspec(dllimport)
#endif

typedef std::chrono::steady_clock::time_point tpoint;
typedef std::chrono::seconds secs;
typedef std::chrono::milliseconds millis;
typedef std::chrono::microseconds micros;
typedef std::chrono::nanoseconds nanos;
using std::chrono::duration_cast;
const auto tnow = std::chrono::high_resolution_clock::now;

extern "C" {
    CFAMILY_API void ResetTimer();
    CFAMILY_API void StartTimer();
    CFAMILY_API void FinishTimer();
    CFAMILY_API long long GetTimer();
    CFAMILY_API long long GetTimerMillis();
    CFAMILY_API long long GetTimerMicros();
    CFAMILY_API long long GetTimerNanos();
}

module.cpp

#include "pch.h"
#include "module.hpp"

static auto start_time = tpoint();
static auto end_time = tpoint();

void ResetTimer()
{
    start_time = tpoint();
    end_time = tpoint();
}

void StartTimer() { start_time = tnow(); }

void FinishTimer() { end_time = tnow(); }

long long GetTimer() { return duration_cast<secs>(end_time - start_time).count(); }

long long GetTimerMillis() { return duration_cast<millis>(end_time - start_time).count(); }

long long GetTimerMicros() { return duration_cast<micros>(end_time - start_time).count(); }

long long GetTimerNanos() { return duration_cast<nanos>(end_time - start_time).count(); }
  1. 然后在我的 clion 项目中我想使用它:main.cpp
#include <iostream>
// include my benchmark.dll here and use its methods

int main() {
    // StartTimer(); in dll
    for (int i = 0; i < 1000000; i++) continue;
    // FinishTimer(); in dll
    // cout << GetTimerNanos() << endl;

    return 0;
}

cmakelists.txt

cmake_minimum_required(VERSION 3.17)
project(SpeedTest)

set(CMAKE_CXX_STANDARD 20)

add_executable(SpeedTest main.cpp)

find_library(${PROJECT_NAME}
    NAMES Benchmark
    HINTS "D:\\VS Projects\\BenchmarkLibrary\\C-Family\\Release-output\\x64")

【问题讨论】:

  • find_library 只搜索库文件。对于与图书馆的链接,您仍然需要target_link_libraries(SpeedTest ${${PROJECT_NAME}})。那么,究竟是什么不起作用?你有错误信息吗?
  • 整个问题分为两点:第一如何给我的dll添加引用? 第二如何使用和调用main.cpp里面的dll函数。谢谢
  • "如何添加对我的 dll 的引用?" - 您是否询问如何与您的图书馆链接?如果是,请查看that question 并给出答案。 (要与 Windows 上的共享库链接,您需要有 import 文件 (.lib)。“如何在 main.cpp 中使用和调用 dll 函数” - 只需 #include &lt;module.h&gt; 并调用头文件中定义的函数。如需帮助#include 查找头文件,请使用include_directoriestarget_include_directories 命令指定包含目录。
  • 好的,谢谢您的回答。但那是静态链接。我想要在运行时进行动态链接。有可能吗?
  • .lib 文件伴随着静态和动态链接。只需谷歌即可了解导入文件对 dll 的意义。

标签: c++ visual-studio c++11 dll cmake


【解决方案1】:

如果.dll的绝对目录是"D:\\VS Projects\\BenchmarkLibrary\\C-Family\\Release-output\\x64",那么你只需要添加以下而不是find_library语句。它只是像评论所说的那样搜索图书馆。

target_link_directories(SpeedTest 
    PRIVATE
    "D:\\VS Projects\\BenchmarkLibrary\\C-Family\\Release-output\\x64"
)
target_link_libraries(SpeedTest PRIVATE Benchmark)
    

更新

要调用函数,请使用与您的库关联的标头。使用绝对目录包含它或编辑您的CMakeLists.txt 文件以添加该目录,然后使用标题的名称,即在您的module.hpp 中,使用#include"someHeader.hpp",然后您可以使用在someHeader.hpp 中声明的函数


要包含您的标题目录,请修改您的CMakeLists.txt 以添加

target_include_directories(SpeedTest PRIVATE "The dir. of the header")

【讨论】:

  • 谢谢。但是有没有像 csharp 这样我们使用DllImport 的方法?
  • @MMD 我不知道C#,但你说过r 使用CMakeCLion,我认为这是使用你使用的工具的最佳方式。
【解决方案2】:

我还找到了另一个关于使用 Libloaderapi.h 的解决方案,它包含在 windows.h 中。

但我更喜欢用@asmmo说的方式

代码如下:

#include <iostream>
#include <windows.h>

using namespace std;

typedef long long (__cdecl *long64F)();

typedef void (__cdecl *voidF)();

int main() {
    HMODULE hmodule = LoadLibraryA(R"(D:\VS Projects\BenchmarkLibrary\C-Family\Release-output\Win32\Benchmark.dll)");
    
    auto reset_timer = (voidF) GetProcAddress(hmodule, "ResetTimer");
    auto start_timer = (voidF) GetProcAddress(hmodule, "StartTimer");
    auto finish_timer = (voidF) GetProcAddress(hmodule, "FinishTimer");
    auto get_timer = (long64F) GetProcAddress(hmodule, "GetTimer");
    auto get_timer_millis = (long64F) GetProcAddress(hmodule, "GetTimerMillis");
    auto get_timer_micros = (long64F) GetProcAddress(hmodule, "GetTimerMicros");
    auto get_timer_nanos = (long64F) GetProcAddress(hmodule, "GetTimerNanos");
    
    cout << "for 1,000,000 times\n"
         << "---------------------" << endl;
    
    start_timer();
    for (int i = 0; i < 1000000; ++i) continue;
    finish_timer();
    
    cout << "time passed in secs:\t" << get_timer() << endl;
    cout << "time passed in millis:\t" << get_timer_millis() << endl;
    cout << "time passed in micros:\t" << get_timer_micros() << endl;
    cout << "time passed in nanos:\t" << get_timer_nanos() << endl;
    reset_timer();
    
    FreeLibrary(hmodule);
    return 0;
}

【讨论】:

    猜你喜欢
    • 2011-06-07
    • 1970-01-01
    • 2018-12-28
    • 2023-03-15
    • 2012-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多