我正在使用JNA来调用user32.dll和kernel32.dll的方法。它现在工作正常。我遇到了一些问题,我知道我必须调用这个方法。
void SendCommandToConsole( char* Cmd )
{
DWORD dwCall = 0x004C1030;
__asm
{
push Cmd;
push 0;
call dwCall;
}
}
SendCommandToConsole ( "rp 2000" );
但我甚至不知道它是什么? __asm在做什么?
如果我使用的标签不正确,请添加适当的标签。 :)
修改的 建议添加.Net和C#标签。上面的代码在C#或.NET中,可能是具有该语言知识的人可以告诉我们它实际上是什么,以及我们如何在java中执行此操作。
答案 0 :(得分:5)
只是为了展示幕后发生的事情:
您的电话:
SendCommandToConsole(“rp 2000”);
使用类型为(char * Cmd)的参数调用函数(SendCommandToConsole)。
在上面的例子中,(char * Cmd)等于“rp 2000”的字符串(sic)。
现在发生的事情是,更高级别的语言(在您的示例中为Java)需要告诉低级语言如何用他们理解的语言解释他们的指令。
所以上面的示例(“我想用”rp 2000“的字符串参数调用函数”SendCommandToConsole“),意味着我们需要与低级语言进行通信:
“首先,那个地址的家伙只想知道两件事情,他们必须按顺序排列:
“好的,这很容易”
我会断言我希望他做什么:
好吧,我会打电话给你......你现在可以继续你的一天。
(因为这是一个“无效”的回报,这意味着你不关心交易的结果)
答案 1 :(得分:2)
这意味着接下来是汇编代码块。
dwCall是指向一个带有一个参数的汇编过程的指针 - >指向堆栈上零终止字节数组的指针。为了正确调用它,你必须将指针推到堆栈上,你只能通过汇编程序来完成。
答案 2 :(得分:2)
在JNA中,您可以使用Function.getFunction(Pointer)
来获取可用于控制特定地址上的调用的对象。
Function dwCall = Function.getFunction(new Pointer(0x12345678));
String CMD = "SomeCommand";
Integer ARG = new Integer(0);
dwCall.invoke(void.class, new Object[CMD, ARG]);
假设该函数使用C调用约定,上面的代码将起作用。最终,您可能希望动态查找函数地址而不是硬编码,并且您可能希望使用JNA Callback而不是直接调用Function对象,但上面的代码提供了您要求的简单功能for(你应该改写原来的问题;你不想执行汇编代码,你想在给定地址调用函数)。
使用JNA回调映射将允许您更自然地调用该函数。
// Use StdCallCallback if the function called uses stdcall rather than cdecl
public class MyCallback extends Callback {
void invoke(String cmd, int arg);
}
Pointer addr = new Pointer(0x1235678);
MyCallback cb = (MyCallback)CallbackReference.getCallback(MyCallback.class, addr);
cb.invoke("SomeCommand", 0);
请注意,这两个示例都假设您已经使用JNA加载有问题的DLL,通常是通过Native.loadLibrary()
。
另请注意,签名实际上可能是void dwCall(int arg, String cmd)
; cdecl和stdcall约定从右到左推送堆栈上的参数,目前我的想法还不够清晰,无法通过正确映射...
答案 3 :(得分:1)
没有Java等价物,Java不允许这种低级控制。您需要将C代码编译为DLL并使用JNA / JNI来调用它。
编辑1:以上仅适用于汇编代码。有关使用JNA在地址上调用stdcall或cdecl函数的信息,请参阅techomage的回复。
__asm块允许您在C源文件中使用程序集。汇编代码调用地址0x004C1030处的函数(无论函数是什么)通过指针传递字符串和零作为参数。
直接调用地址是个坏主意。你可能不会得到你期望的东西,除非你知道程序的低级内部和你的操作系统真的很好。调用它很可能会导致程序崩溃。
答案 4 :(得分:0)
为什么不只是调用SendCommandToConsole()
函数?该函数正在做的是进行Windows系统调用而你不应该编写一个执行该操作的函数,你应该调用一个函数来执行该操作。
答案 5 :(得分:0)
我想真正的问题是" rp 2000"做?如果它使用参数2000运行rp.exe,那么你可以使用java.lang.Runtime来做同样的事情。如果我们知道它做了什么,那么java中可能会有一些东西可以做到。