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

c0d*_*een 5 c dll 64-bit compilation x86-64

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

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

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

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

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

Cri*_*ati 1

正如我在 [SO] 开头所解释的:如何构建 libjpeg 9b 的 DLL 版本?(@CristiFati 的回答)(来自1. 准备地面部分的要点),有不同的方法可以处理从VStudio中的命令行构建。
我将重点关注vcvarsall.bat。有关 [MSDN] 的更多详细信息:设置命令行构建的路径和环境变量(它是VStudio2015,因为VStudio2017链接已损坏)。
我准备了一个虚拟示例。

代码.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;
}
Run Code Online (Sandbox Code Playgroud)

建造

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
Run Code Online (Sandbox Code Playgroud)

注意事项

  • 我的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
>>>
Run Code Online (Sandbox Code Playgroud)