在 Windows 上使用 cl.exe 和 powershell 但不使用 CMake、MSBuild 或 Visual Studio 编译动态链接库 (DLL)

问题描述 投票:0回答:1

我想了解如何编译和链接 Windows 上的动态链接库。我通常会使用 CMake 来完成此类任务,但我想了解如何在没有 CMake(或任何其他构建系统)的情况下实现它。我正在寻找可以输入 powershell 的原始命令。

在 UNIX 上,这相当简单,但在 Windows 上我似乎遇到了困难,似乎没有任何好的资源,至少在过去几天里我找不到(无论是在 stackoverflow 还是在其他任何地方)。有一些解决方案接近我的问题,但他们无法澄清我的所有问题,因此我在这里问这个问题。

我编写了一个简单的玩具项目,应该有助于澄清我遇到的问题。

项目结构如下:

root
├── build
├── lib
│   ├── myMathLib.h
│   └── myMathLib.cpp
├── main.cpp
└── compileAndRun.bat

lib
文件夹中,我有以下文件及其内容:

// myMathLib.h
#pragma once

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
  #ifdef COMPILED
    #define API __declspec(dllexport)
  #else
    #define API __declspec(dllimport)
  #endif
#endif

extern "C" {

class MyMathLib {
public:
  API int add(int a, int b);
};

}
// myMathLib.cpp
#include "lib/myMathLib.h"

int MyMathLib::add(int a, int b) {
  return a + b;
}

主文件只是调用这个函数:

// main.cpp
#include <iostream>
#include "lib/myMathLib.h"

int main() {
  MyMathLib math;
  std::cout << "2 + 3 = " << math.add(2, 3) << std::endl;
  return 0;
}

我的

compileAndRun.bat
文件看起来如下

@echo off

del /q build
mkdir build

REM compile source files into object code
cl /nologo /c /EHsc /Od /I. /DCOMPILED lib/myMathLib.cpp /Fobuild\myMathLib.obj
cl /nologo /c /EHsc /Od /I. main.cpp /Fobuild\main.obj

REM link object files into dynamic library
link /nologo /DLL /OUT:build\libMyMath.dll build\myMathLib.obj

REM compile main function and link library into executable
cl /nologo /EHsc /Od /I. build\main.obj /Fe:build\dynamicLibExample.exe /link /DLL /LIBPATH:build build\libMyMath.dll 

REM remove object files
del build\*.obj

REM run
echo Running dynamic library example
build\dynamicLibExample.exe

在此脚本中,我可以编译源文件,甚至可以在

libMyMath.dll
文件夹中创建
build
文件。但是,当我尝试将我的
main.obj
文件链接到动态库(第 14 行)时,我收到
build\libMyMath.dll : fatal error LNK1107: invalid or corrupt file: cannot read at 0x2F8
编译器错误,并且我无法继续前进,所以我的问题是如何链接它现在针对我的
main.cpp
文件生成 DLL 文件。

还有一个问题:如果我只打算在 C++ 代码库中使用此代码,我是否需要

extern "C"
?我认为名称修改不是问题,所以我可能会放弃它,但我看到其他人都在这样做,但我认为这只是为了使其也可用于 C。

还有一个澄清:我知道

__declspec(dllexport)
__declspec(dllimport)
仅适用于 Windows 平台,但根据我所读到的内容,我可以摆脱它们并提供
*.def
文件。从我读到的内容来看,这似乎不是首选方法,但如果有人可以展示(再次,出于教育目的)我如何在没有
#pragma
的情况下使用
*.def
文件实现库代码,那就会了非常感谢。

c++ powershell dll dllimport dllexport
1个回答
0
投票

链接 DLL 时,会创建导入库 libMyMath.lib。该库具有与静态库相同的 .lib 扩展名,但它不包含函数的代码。只有调用 DLL 中实现的函数存根。

当您构建 EXE 文件时,您必须链接 LIB 而不是 DLL:

cl /nologo /EHsc /Od /I. build\main.obj /Fe:build\dynamicLibExample.exe /link /DLL /LIBPATH:build build\libMyMath.lib 
© www.soinside.com 2019 - 2024. All rights reserved.