Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PonyLang Windows CreateProcess FFI_Windows_Ffi_Pony_Ponylang - Fatal编程技术网

PonyLang Windows CreateProcess FFI

PonyLang Windows CreateProcess FFI,windows,ffi,pony,ponylang,Windows,Ffi,Pony,Ponylang,我一直在尝试从小马语言的FFI调用Window的CreateProcessA 我创建了一个C和一个Ponelang示例。C示例非常有用: #include <windows.h> #include <stdio.h> #include <tchar.h> void wmain(void) { STARTUPINFO info={0}; PROCESS_INFORMATION processInfo={0}; CreateProces

我一直在尝试从小马语言的FFI调用Window的
CreateProcessA

我创建了一个C和一个Ponelang示例。C示例非常有用:

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

void wmain(void) {
    STARTUPINFO info={0};
    PROCESS_INFORMATION processInfo={0};

    CreateProcessA("calc.exe", 0, 0, 0, 0, 0, 0, 0, &info, &processInfo);

    if (status == 0)
        printf("%d",GetLastError()); // never hits

}
因此,上面的代码为PonyLang编译,但大部分时间返回2。有时
GetLastError
返回123。其他时候它返回998? 有时错误代码是不同的,这似乎很奇怪。这些代码都意味着文件访问有问题

Calc.exe
位于当前目录中(与c示例相同的目录)

此外,不仅错误代码不同,而且calc.exe在C版本中执行(运行正常),而在PonyLang版本中不执行。这让我相信我的蓬莱ffi设置出了问题


有人知道可能出了什么问题吗

问题在于您使用的
addressof
。当您创建一个
struct
对象时,例如使用
var si=StartupInfo
,底层类型是指向该结构的指针(例如,Pony中的
struct
s没有值语义)。然后,当您使用
addressof
调用
CreateProcessA
时,实际上是在传递一个指向函数指针的指针


如果您的C函数需要一个指向结构的指针,那么在执行FFI调用时,您只需传递Pony对象而无需
addressof

问题在于使用
addressof
。当您创建一个
struct
对象时,例如使用
var si=StartupInfo
,底层类型是指向该结构的指针(例如,Pony中的
struct
s没有值语义)。然后,当您使用
addressof
调用
CreateProcessA
时,实际上是在传递一个指向函数指针的指针


如果您的C函数需要指向结构的指针,则在执行FFI调用时,只需传递Pony对象,而无需
addressof

您的C代码与PonyLang代码有相同的错误,并且只能在巧合的情况下工作。您必须检查CreateProcess的返回值以确定是否发生了错误。只有在发生错误时,调用GetLastError()来确定错误代码才有意义。如果没有发生错误,GetLastError()可能会返回任何内容,但不保证返回零。对,但是C显示calc.exe,而PonyLang则显示nothing。谢谢你的提示。我将检查返回值。看起来您假设
BOOL
是一种8位类型,实际上是32位,这可能是造成问题的原因?(CreateProcess的两个参数也是指针类型的,所以如果您碰巧正在构建一个64位应用程序,它们将需要64位而不是32位。)FWIW,代码998明确表示某种参数错误,它与文件访问无关。(您确定
=“”.cstring
会导致字段被初始化为空指针吗?),所以你可以看到你正在做的调用实际上看起来像Windows。你的C代码和你的Ponelang代码有相同的bug,只是巧合。您必须检查CreateProcess的返回值以确定是否发生了错误。只有在发生错误时,调用GetLastError()来确定错误代码才有意义。如果没有发生错误,GetLastError()可能会返回任何内容,但不保证返回零。对,但是C显示calc.exe,而PonyLang则显示nothing。谢谢你的提示。我将检查返回值。看起来您假设
BOOL
是一种8位类型,实际上是32位,这可能是造成问题的原因?(CreateProcess的两个参数也是指针类型的,所以如果您碰巧正在构建一个64位应用程序,它们将需要64位而不是32位。)FWIW,代码998明确表示某种参数错误,它与文件访问无关。(您确定
=“”.cstring
会导致字段被初始化为空指针吗?)也许您可以编写一个小型的C DLL,导出一个与CreateProcess具有相同签名的函数,然后调用它,这样您就可以看到您正在进行的调用实际上与Windows类似。感谢您提供的提示。然而我现在收到错误123,这意味着类似于以前的错误(无效文件名等)。MSDN提到此字段是结构的地址(本身不是指针)。如果你提到小马不能通过混凝土结构;我应该用一个简单的接口创建自己的dll并调用它吗?是的,实现一个shim C层可能会更容易。小马FFI仍然非常简单,不适合处理复杂的API。谢谢你的提示。然而我现在收到错误123,这意味着类似于以前的错误(无效文件名等)。MSDN提到此字段是结构的地址(本身不是指针)。如果你提到小马不能通过混凝土结构;我应该用一个简单的接口创建自己的dll并调用它吗?是的,实现一个shim C层可能会更容易。Pony FFI仍然非常简单,不适合处理复杂的API。
use "lib:kernel32"

primitive _ProcessAttributes
primitive _ThreadAttributes
primitive _Inherit
primitive _Creation
primitive _Environment
primitive _CurrentDir
primitive _StartupInfo
primitive _ProcessInfo

primitive _HandleIn
primitive _HandleOut
primitive _HandleErr

primitive _Thread
primitive _Process

struct StartupInfo 
    var cb:I32 = 0
    var lpReserved:Pointer[U8] tag= "".cstring()
    var lpDesktop:Pointer[U8] tag= "".cstring()
    var lpTitle:Pointer[U8] tag= "".cstring()
    var dwX:I32 = 0
    var dwY:I32 = 0
    var dwXSize:I32=0
    var dwYSize:I32=0
    var dwXCountChars:I32=0
    var dwYCountChars:I32=0
    var dwFillAttribute:I32=0
    var dwFlags:I32=0
    var wShowWindow:I16=0
    var cbReserved2:I16=0
    var lpReserved2:Pointer[U8] tag="".cstring()
    var hStdInput:Pointer[_HandleIn] = Pointer[_HandleIn]
    var hStdOutput:Pointer[_HandleOut]= Pointer[_HandleOut]
    var hStdError:Pointer[_HandleErr]= Pointer[_HandleErr]

struct ProcessInfo
    var hProcess:Pointer[_Process] = Pointer[_Process]
    var hThread:Pointer[_Thread] = Pointer[_Thread]
    var dwProcessId:I32 = 0
    var dwThreadId:I32 = 0


//var si:StartupInfo = StartupInfo

actor Main
  new create(env: Env) =>
    var si: StartupInfo = StartupInfo
    var pi: ProcessInfo = ProcessInfo
    var inherit:I8 = 0
    var creation:I32 = 0
    var one:I32 = 0
    var two:I32 = 0
    var three:I32 = 0
    var four:I32 = 0
    var z:I32 = 0

    var p = @CreateProcessA[I8]("calc.exe",
    z,
    one,
    two,
    inherit,
    creation,
    three,
    four,
    addressof si,
    addressof pi)

    if p == 0 then
        var err = @GetLastError[I32]() // hits this every time.
        env.out.print("Last Error: " + err.string())
    end