如何编译用 C 编写的 64 位 dll? [英] How to compile a 64-bit dll written in C?

查看:67
本文介绍了如何编译用 C 编写的 64 位 dll?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

我使用的是 Visual Studio 2017 附带的 cl.exe

更新:我在 C:Program Files (x86)Microsoft Visual Studio2017CommunityVCToolsMSVC14.13 下找到了 64 位 cl.exe.26128inHostx64x64cl.exe,但是在运行它时,我收到一个错误,指出库机器类型(x86)与目标类型(x64)冲突.如何更改库机器类型?

解决方案

正如我在 [SO]:如何构建 libjpeg 9b 的 DLL 版本?(@CristiFati 的回答)(来自 1. 准备地面 部分的项目符号),在 VStudio 中有多种方法可以从命令行处理构建.
我将专注于vcvarsall.bat.有关 [MSDN]:设置路径和命令行构建的环境变量(这是 VStudio2015,因为 VStudio2017 链接已损坏).
我准备了一个虚拟示例.

code.c:

#include #include "jni.h"__declspec(dllexport) int func() {JavaVMInitArgs 参数;printf("指针大小:%lld 位
", sizeof(void*) * 8);printf("JNI_GetDefaultJavaVMInitArgs 返回:%d
", JNI_GetDefaultJavaVMInitArgs(&args));返回0;}

构建:

<块引用>

e:WorkDevStackOverflowq050164687>"c:Installx86MicrosoftVisual Studio Community2017VCAuxiliaryBuildvcvarsall.bat" amd64**************************************************************************** Visual Studio 2017 开发人员命令提示符 v15.6.6** 版权所有 (c) 2017 Microsoft Corporation**************************************************************************[vcvarsall.bat] 环境初始化为:'x64'e:WorkDevStackOverflowq050164687>dir/b代码.ce:WorkDevStackOverflowq050164687>cl/nologo/LD/I"c:Installx64OracleJavajdk1.8.0_152include"/I"c:Installx64OracleJavajdk1.8.0_152includewin32"/DWIN64/DWIN32 code.c/link/LIBPATH:"c:Installx64OracleJavajdk1.8.0_152lib"/OUT:dummy.dll jvm.lib代码.c创建库 code.lib 和对象 code.expe:WorkDevStackOverflowq050164687>dir/b代码.c代码.exp代码库代码.obj虚拟文件

注意事项:

  • 我的 vcvarsall 路径是自定义的,因为我在C:Installx86MicrosoftVisual Studio Community2017 下安装了 VStudio2017".默认路径为%SystemDrive%Program Files (x86)Microsoft Visual Studio2017Community"
  • 运行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:WorkDevStackOverflowq050164687>set PATH=%PATH%;c:Installx64OracleJavajdk1.8.0_152jreinservere:WorkDevStackOverflowq050164687>"e:WorkDevVEnvspy35x64_testScriptspython.exe"Win32 上的 Python 3.5.4(v3.5.4:3f56838,2017 年 8 月 8 日,02:17:05)[MSC v.1900 64 位 (AMD64)]输入帮助"、版权"、信用"或许可证"以获取更多信息.>>>导入 ctypes>>>dummy = ctypes.CDLL("dummy.dll")>>>dummy.func()指针大小:64 位JNI_GetDefaultJavaVMInitArgs 返回:-10>>>

I have a Java program which makes use of some native function calls to speed up video encoding. It requires a DLL, which I will write in C (I have just a test one right now).

When I compile the DLL with cl /I "java-path/include" /"java-path/include/win32" -DL -ML Main.c -FeTest.dll it compiles, but I get a 32-bit DLL. After I did some research on the internet, I found out that I would need a 64-bit DLL instead.

After more research, I have found this post which is the only one for C (even C++ was hard to find), but this only works if you are writing/building via Visual Studio 2010. I am using Elipse for the Java, CLion for the C, and compiling via the "Developer Command Prompt." so this does not work for me. How might I recompile as a 64-bit DLL?

EDIT: I am using the cl.exe that comes with Visual Studio 2017

UPDATE: I found the 64-bit cl.exe under C:Program Files (x86)Microsoft Visual Studio2017CommunityVCToolsMSVC14.13.26128inHostx64x64cl.exe, however when running it, I get an error that the library machine type (x86) conflicts with the target type (x64). How do I change the library machine type?

解决方案

As I explained at the beginning of [SO]: How to build a DLL version of libjpeg 9b? (@CristiFati's answer) (bullets from 1. Prepare the ground section), there are different ways to deal with building from command line in VStudio.
I'm going to focus on vcvarsall.bat. More details on [MSDN]: Setting the Path and Environment Variables for Command-Line Builds (It's VStudio2015 as VStudio2017 link is broken).
I prepared a dummy example.

code.c:

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


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

Build:

e:WorkDevStackOverflowq050164687>"c:Installx86MicrosoftVisual Studio Community2017VCAuxiliaryBuildvcvarsall.bat" amd64
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.6.6
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'

e:WorkDevStackOverflowq050164687>dir /b
code.c

e:WorkDevStackOverflowq050164687>cl /nologo /LD /I"c:Installx64OracleJavajdk1.8.0_152include" /I"c:Installx64OracleJavajdk1.8.0_152includewin32" /DWIN64 /DWIN32 code.c /link /LIBPATH:"c:Installx64OracleJavajdk1.8.0_152lib" /OUT:dummy.dll jvm.lib
code.c
   Creating library code.lib and object code.exp

e:WorkDevStackOverflowq050164687>dir /b
code.c
code.exp
code.lib
code.obj
dummy.dll

Notes:

  • My vcvarsall path is custom, because I installed VStudio2017 under "C:Installx86MicrosoftVisual Studio Community2017". Default path is "%SystemDrive%Program Files (x86)Microsoft Visual Studio2017Community"
  • After running vcvarsall, I don't have to specify to cl.exe (or link.exe):
    • The full path
    • Build options (architecture specific, including paths)
    • I still have to specify things that it doesn't know about (like Java stuff)
  • In order to test the newly built .dll, I'm going to use Python, as it's easier than writing another .c program that uses it
  • Since I linked the .dll to jvm.lib, at runtime it will need jvm.dll, so I'm adding its path into %PATH%
  • I built my code with VStudio2017 (VCRuntime14.0), but jvm.dll is linked to VCRuntime10.0 (VStudio2010), meaning that there will be (at least) 2 VCRuntimes loaded in my program. That is to be avoided as it could lead to all kinds of nasty problems

e:WorkDevStackOverflowq050164687>set PATH=%PATH%;c:Installx64OracleJavajdk1.8.0_152jreinserver

e:WorkDevStackOverflowq050164687>"e:WorkDevVEnvspy35x64_testScriptspython.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 编写的 64 位 dll?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆