c - 如何编译用 C 编写的 64 位 dll?

标签 c dll compilation 64-bit x86-64

我有一个 Java 程序,它利用一些 native 函数调用来加速视频编码。它需要一个 DLL,我将用 C 编写它(我现在只有一个测试)。

当我使用 cl/I "java-path/include"/"java-path/include/win32"-DL -ML Main.c -FeTest.dll 编译 DLL 时,它会编译,但我得到了一个 32 位 DLL。在互联网上做了一些研究后,我发现我需要一个 64 位 DLL。

经过更多研究,我找到了this post这是 C 的唯一一个(甚至 C++ 也很难找到),但这只有在您通过 Visual Studio 2010 编写/构建时才有效。我使用 Elipse 用于 Java,CLion 用于 C,并通过“开发人员”进行编译命令提示符。”所以这对我不起作用。我如何重新编译为 64 位 DLL?

编辑:我正在使用 Visual Studio 2017 附带的 cl.exe

更新:我在 C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13 下找到了 64 位的 cl.exe。 26128\bin\Hostx64\x64\cl.exe,但是在运行它时,出现库机器类型 (x86) 与目标类型 (x64) 冲突的错误。如何更改图书馆机器类型?

最佳答案

正如我在 [SO]: How to build a DLL version of libjpeg 9b? (@CristiFati's answer) 开头所解释的那样(来自 1. Prepare the ground 部分的项目符号),VStudio 中有不同的命令行处理构建的方法。
我将专注于vcvarsall.bat。有关 [MSDN]: Setting the Path and Environment Variables for Command-Line Builds 的更多详细信息(它是 VStudio2015,因为 VStudio2017 链接已损坏)。
我准备了一个虚拟例子。

code.c:

#include <stdio.h>
#include "jni.h"


__declspec(dllexport) int func() {
    JavaVMInitArgs args;
    printf("Pointer size: %lld bits\n", sizeof(void*) * 8);
    printf("JNI_GetDefaultJavaVMInitArgs returned: %d\n", JNI_GetDefaultJavaVMInitArgs(&args));
    return 0;
}

构建:

e:\Work\Dev\StackOverflow\q050164687>"c:\Install\x86\Microsoft\Visual Studio Community\2017\VC\Auxiliary\Build\vcvarsall.bat" amd64
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.6.6
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'

e:\Work\Dev\StackOverflow\q050164687>dir /b
code.c

e:\Work\Dev\StackOverflow\q050164687>cl /nologo /LD /I"c:\Install\x64\Oracle\Java\jdk1.8.0_152\include" /I"c:\Install\x64\Oracle\Java\jdk1.8.0_152\include\win32" /DWIN64 /DWIN32 code.c /link /LIBPATH:"c:\Install\x64\Oracle\Java\jdk1.8.0_152\lib" /OUT:dummy.dll jvm.lib
code.c
   Creating library code.lib and object code.exp

e:\Work\Dev\StackOverflow\q050164687>dir /b
code.c
code.exp
code.lib
code.obj
dummy.dll

注意事项:

  • 我的 vcvarsall 路径是自定义的,因为我在“C:\Install\x86\Microsoft\Visual Studio Community\2017 下安装了 VStudio2017 ”。默认路径为“%SystemDrive%\Program Files (x86)\Microsoft Visual Studio\2017\Community
  • 运行 vcvarsall 后,我不必指定到 cl.exe(或 link.exe):
    • 完整路径
    • 构建选项(特定于架构,包括路径)
    • 我仍然需要指定它不知道的东西(比如 Java 东西)
  • 为了测试新建的 .dll,我将使用 Python,因为它比编写另一个 .c 更容易使用它的程序
  • 由于我将 .dll 链接到 jvm.lib,在运行时它将需要 jvm.dll,所以我添加了它进入 %PATH%
  • 的路径
  • 我使用 VStudio2017 (VCRuntime14.0) 构建我的代码,但是 jvm.dll 链接到 VCRuntime10.0 (VStudio2010),这意味着我的程序中将(至少)加载 2 个 VCRuntime。这是要避免的,因为它可能会导致各种讨厌的问题
e:\Work\Dev\StackOverflow\q050164687>set PATH=%PATH%;c:\Install\x64\Oracle\Java\jdk1.8.0_152\jre\bin\server

e:\Work\Dev\StackOverflow\q050164687>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe"
Python 3.5.4 (v3.5.4:3f56838, Aug  8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import ctypes
>>> dummy = ctypes.CDLL("dummy.dll")
>>> dummy.func()
Pointer size: 64 bits
JNI_GetDefaultJavaVMInitArgs returned: -1
0
>>>

关于c - 如何编译用 C 编写的 64 位 dll?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50164687/

相关文章:

c - 创建基本日历程序的逻辑错误

c++ - 如何测试是否定义了只能通过#define 宏访问的标识符?

dll - 是否有与 gcc --kill-at 等效的 Visual C++?

c++ - C/C++ 动态链接如何在不同平台上工作?

c++ - 如何在 Linux 上调用 MinGW 交叉编译器?

swift - 由于抛出的异常,让 Swift 相信函数永远不会返回

c - 为什么在已经定义函数的源代码中添加头文件?

c - 是否存在常量数据应加载到 RAM 而不是直接闪存访问的情况

C++:即使缺少第 3 方 DLL,也允许程序运行?

python - 如何将 Python 模块编译为 dll 并在 VBA 中调用它