【问题标题】:Trying to compile simple dll written in C using gcc fails尝试使用 gcc 编译用 C 编写的简单 dll 失败
【发布时间】:2017-10-10 16:02:24
【问题描述】:

尝试使用 gcc 编译一个用 C 语言编写的简单 DLL。

尝试了许多教程,但即使我将文件剥离到最基本的内容,也无法编译它。

test_dll.c

#include <stdio.h>

__declspec(dllexport) int __stdcall hello() {
    printf ("Hello World!\n");
}

尝试使用命令编译它

gcc -c test_dll.c

失败,得到这个输出

test_dll.c: In function '__declspec':
test_dll.c:3:37: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'hello'
 __declspec(dllexport) int __stdcall hello() {
                                     ^
test_dll.c:5:1: error: expected '{' at end of input
 }
 ^

gcc 版本

gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3)

【问题讨论】:

  • 你在为 windows 编译吗? __declspec(dllexport) 与 windows(导入库)中的特殊链接器语义有关,在其他系统上不存在。
  • 我认为您需要回答这个问题:您的目标输出是针对 Windows 还是 Linux? Windows 使用 DLL,而 Linux(通常)使用 SO。您似乎使用的是 Linux (Ubuntu),所以您是真的想针对不同的操作系统 (Windows),还是想创建一个 SO 以在 Linux 上使用?
  • 是的,我确实在为 Windows 编译。没有意识到我需要交叉编译。谢谢大家。

标签: c gcc dll declspec


【解决方案1】:

这取决于你想做什么:

1。在 linux 上构建 linux 库

然后删除__declspec(dllexport)__stdcall。在 linux 上,构建库的源代码不需要什么特别的东西。请注意,库不是 linux 上的 DLL,它们被命名为 *.so(共享对象)。您必须使用-fPIC 进行编译并与-shared 链接以创建您的.so 文件。请使用谷歌了解更多详情。

2。在linux上构建windows DLL

安装 mingw 包(在你的包管理器中搜索它们)。然后,不只是gcc,而是调用针对 windows/mingw 的交叉编译器,例如i686-w64-mingw32-gcc.

3。允许跨平台构建库,包括 windows

如果您希望能够在 windows 和 linux 上使用相同的代码构建库,则需要一些预处理器魔法,因此 __declespec() 仅在面向 windows 时使用。我通常使用这样的东西:

#undef my___cdecl
#undef SOEXPORT
#undef SOLOCAL
#undef DECLEXPORT

#ifdef __cplusplus
#  define my___cdecl extern "C"
#else
#  define my___cdecl
#endif

#ifndef __GNUC__
#  define __attribute__(x)
#endif

#ifdef _WIN32
#  define SOEXPORT my___cdecl __declspec(dllexport)
#  define SOLOCAL
#else
#  define DECLEXPORT my___cdecl
#  if __GNUC__ >= 4
#    define SOEXPORT my___cdecl __attribute__((visibility("default")))
#    define SOLOCAL __attribute__((visibility("hidden")))
#  else
#    define SOEXPORT my___cdecl
#    define SOLOCAL
#  endif
#endif

#ifdef _WIN32
#  undef DECLEXPORT
#  ifdef BUILDING_MYLIB
#    define DECLEXPORT __declspec(dllexport)
#  else
#    ifdef MYLIB_STATIC
#      define DECLEXPORT my___cdecl
#    else
#      define DECLEXPORT my___cdecl __declspec(dllimport)
#    endif
#  endif
#endif

然后将DECLEXPORT放在要由lib导出的每个声明前面,并将SOEXPORT放在每个定义前面。这只是一个简单的例子。

【讨论】:

  • 您似乎错过了他在 Windows 上为 Windows 编写 DLL 并使用 gcc 的替代方案。赛格温。 Cygwin btw 的答案与您的第 1 部分相同,但不需要 -fPic
  • @JeremyP 不,问题明确指出gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
  • OK 没看到。
  • 也许是新的 windows 10 ubuntu 子系统 ;)
  • 我确实听说微软正在为 Windows 11 试用新内核,该内核使用核心 Linux 内核和 NT 系统调用的兼容层。
【解决方案2】:

由于您在 Linux 上编译,gcc 将 Linux 作为目标。

您要做的是针对 Windows 进行交叉编译。这意味着您将需要一个交叉编译器。可用于 Ubuntu Linux 的是 mingw。

您可以使用安装它

apt-get install gcc-mingw32 

然后就可以编译了

gcc-mingw32 -c test_dll.c

需要进一步编译成dll

gcc-mingw32 --shared test_dll.o -o test_dll.dll

这个 dll 然后可以在 Windows 上使用。

【讨论】:

  • 谢谢,这有效,但菲利克斯先回答,所以我标记了他的回答。
  • 无论如何它更详细,并探索了所有可能的情况。所以,是的,我不介意。
  • 对于交叉编译案例来说仍然是一个很好的答案,所以在这里支持 - 我有点惊讶,Ubuntu真的调用了gcc的mingw变体gcc-mingw32?这不符合惯例 ([target-triplet]-gcc) :o
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-11
  • 1970-01-01
  • 1970-01-01
  • 2015-02-13
  • 2017-08-28
  • 1970-01-01
  • 2010-09-11
相关资源
最近更新 更多