将本机C#调用转换为Java(使用JNA)

将本机C#调用转换为Java(使用JNA),c#,java,jna,C#,Java,Jna,我是新来的。此外,我还需要一些帮助,帮助我使用JNA调用本机Windows函数,将一些C#代码转换为Java 首先也是最重要的是,这是我试图转换的代码: 到目前为止,我已经编写了JNA接口来表示内核32和NtDll库。在Kernel32库中,我还定义了需要使用的结构 Kernel32.java NtDll.java 在定义了库和结构之后,我开始编写非本机函数。问题是,我不理解所有的C#语法。但是,我确实了解C#中的所有Java特性 这是我到目前为止写的东西;请注意,我已经评论了我不理解的内

我是新来的。此外,我还需要一些帮助,帮助我使用JNA调用本机Windows函数,将一些C#代码转换为Java

首先也是最重要的是,这是我试图转换的代码:

到目前为止,我已经编写了JNA接口来表示内核32和NtDll库。在Kernel32库中,我还定义了需要使用的结构

Kernel32.java

NtDll.java

在定义了库和结构之后,我开始编写非本机函数。问题是,我不理解所有的C#语法。但是,我确实了解C#中的所有Java特性

这是我到目前为止写的东西;请注意,我已经评论了我不理解的内容,以及我是否对我的转换有疑问。大多数问题都会重复,这意味着,如果你给我提供一个转换,我就可能知道如何完成其余的转换。感谢您的帮助!:-)


不要学究气,但不要那样做。您正在尝试在JVM中运行C#程序?编写一个抽象出应用程序特定于操作系统的部分的层会更简单、更快。在C语言中可以做一些在JVM中不起作用的事情。例如加载DLL,然后在其中调用方法。或者从windows消息循环获取消息

现在,我同意您可能想做的一些事情只能从本机库中完成。喜欢与其他窗口交互。但是您正在用Java实现CLR。这是一个巨大的工作量,有些部分永远不会工作

不要这样做。(在此处插入nike swoosh)

因此您的Kine.Run()看起来像是此代码的主要入口点。它所做的是获取给定的字节数组,分叉当前进程,然后用字节数组覆盖当前进程内存并开始执行它。如果您实现了这一点,您将作为子进程运行字节数组

现在,假设字节数组来自文件系统中的某个文件(或者可以写入其中),您可以用以下行替换所有代码:

Runtime.getRuntime().exec(filename);

假设文件名是包含字节数组的文件。无需了解PE封头或windows内部构件。如果字节数组来自无法在本地存储的地方,那么无论如何您都无法运行它。

一般来说,您甚至不会执行任何特定于C#的操作,而是执行基本的C指针算法

绕过数据块并在数据类型之间执行转换的最简单方法是使用
com.sun.jna.Memory
而不是
byte[]
。您可以使用
Pointer.share(长偏移量)
执行指针算法(结果是原始指针偏移量与请求量之比)。您可以使用各种
指针.write()
指针.readXXX()
变体读取和写入本机内存

您可以使用
指针
作为基址初始化Java端
结构
对象,只需记住显式调用
Structure.read()
将本机内存同步到Java即可

举几个例子,从你的馅饼:

Memory data = ...;
// mzH = *(MZHeader*) dPtr;
MZHeader mzH = new MZHeader(data);
mzH.read(); // or put this in the MZHeader(Pointer) ctor
// peH = *(PE_Header*)&dPtr[mzH.offsetToPE];
PE_Header peH = new PE_Header(data.share(mzH.offsetToPE));
peH.read(); // or put this in the PE_Header(Pointer) ctor
// peXH = *(PE_ExtHeader*)&dPtr[mzH.offsetToPE + sizeof(PE_Header)];
PE_ExtHeader peXH = new PE_ExtHeader(data.share(mzH.offsetToPE + peH.size()));
peXH.read(); // or put this in the PE_ExtHeader(Pointer) actor
我想你可以从那里得到这个想法

编辑

Pointer p = new Memory();
byte[] data = ...;
// Copy into Memory from data
p.write(0, data, 0, data.length);
// Copy out of Memory into data
p.read(0, data, 0, data.length);

嗯,你在说什么?我正在把一个C#程序改写成Java。C#使用本机调用,我使用JNA在Java中进行本机调用。问题不是加载DLL和调用方法,而是将实现C#代码转换为Java。我没有在Java中重新实现CLR,我不知道这是从哪里来的。你看过我要翻译的代码了吗?如果你在重写c程序,你就不需要JNA调用了。您可以用java等价物重写这些c#调用。您应该更改应用程序代码,而不是编写CLR等效函数。为什么您的应用程序需要写入其他进程的内存空间?但我需要JNA调用,因为它们是应用程序的主要部分。应用程序的任务是执行字节数组(构成可执行文件),而不让可执行文件进入硬盘。请查看我遇到问题的代码,它在注释中显示了我遇到的问题,因为我不知道Java等价物。本机调用不是我的问题。您粘贴的代码没有显示应用程序的功能。它只表明您正在尝试创建流程。我认为你们处理这个问题的水平太低了。如果您正在编写脚本环境,那么您需要在java中实际实现脚本原语。可以使用java.nio.ByteBuffer读取字节数组(以及短字节、整数、长字节、浮点和双字节!),然后处理每个操作码。JVM的设计不允许您执行任意机器代码。我不认为这是你想要的方式。你知道你将要执行的代码在做什么吗?你能解释代码,或者把它作为类加载吗?谢谢!这很有帮助!如何从字节数组构造内存对象?还有,使用封送处理副本的等效方法是什么?Marshal.Copy(peBytes,(int)secHdrs[i].pointerToRawData,(IntPtr)ptr,copySize);没有直接的本机到本机内存拷贝,但您可以轻松地映射
memcpy
或类似的C库函数来实现。