从Ruby中调用C代码 - 如何使用返回的指针?

Ass*_*him 6 c ruby windows winapi

问题:

我想在我的Ruby程序中使用一个用C编码并通过DLL公开的算法.

我想将算法视为可以在Ruby中调用的黑盒子 - 只需传入所需的参数并使用结果.

Ruby(1.8.7和1.9.3)都有一个Win32API模块,它似乎可以很容易地与动态库交互,完全按照我的要求进行操作.

但问题是我似乎无法通过Win32API调用来发回字符串.

细节:

第三方C函数是CodeGen().它需要6个参数,包括源字符串,用作加密密钥的任意字符串,以及为简单起见,4个数字参数,一个signed int,一个unsigned long和两个unsigned short.从这些开始,CodeGen()实现了一个黑盒算法来返回一个结果字符串.

CodeGen()的C原型是:

const char *CodeGen(  int encryp_level, 
                     const char *source_str, const char *encryp_key,
                     unsigned long param_a, 
                     unsigned short param_b, unsigned short param_c
                  )
Run Code Online (Sandbox Code Playgroud)

请注意,两个输入字符串都是常量,即它们作为字符串提供给CodeGen() - 因此指向常量字符串

CodeGen()的返回值也是一个固定最大长度的字符串,因此它将返回一个指针.

我的问题:

我如何设置对CodeGen()的调用并获取它应该生成的字符串?

我的尝试:

当我期望获得一个字符串时,下面的代码只是给我整数作为返回值.

require 'Win32API'

codeGen = Win32API.new("encrypt.dll", "CodeGen", "ISSIII", "S")

ret_str = codeGen.Call(3, "foo", "bar", 0, 0, 0)

puts ret_str
Run Code Online (Sandbox Code Playgroud)

但是,我没有得到一个字符串,而是返回一个整数. 编辑:这可能是指针吗?

虽然我在Windows 7,64位版本上使用Ruby 1.9.3,但我也在Windows XP上测试了上述内容,32位,并使用Ruby 1.8.7,所以我很确定这是做的事情我使用Win32API本身.

不确定问题是否是以下任何一个:

  • 需要打包整数(3,0,...)吗?
  • 我需要区分短期和长期类型吗?
  • 我没有正确处理返回值吗?
  • 如果返回值是指针,我如何在Ruby中使用它?
  • 别的什么?

任何见解都将非常感谢!

Ass*_*him 4

虽然我不知道为什么该Win32API方法不起作用,但我找到了一个更简单的解决方案,用于解决FFI从 Ruby 内调用 C 函数或与 DLL 交互的问题。


解决方案使用FFI

在 Ruby 中用于FFI与 DLL 交互,如下所示:

  • (1)安装ffi (适用于ruby 1.9.3,ymmv适用于以前的版本)

    gem install ffi

  • (2) 创建自己的Ruby模块来包装C函数

require 'ffi'

module CodeGen                   # Ruby wrapper  (your choice)
  extend FFI::Library
  ffi_lib 'codegen'              # DLL name  (given)
  attach_function 
        :create_code,            # method name  (your choice)
        :CreateCodeShort3,       # DLL function name (given)
          [ :int, :string, :string, :uint, :ushort, :ushort], :string  
                          # specify C param / return value types 
end

ret_str = CodeGen.create_code(3, "foo", "bar", 0,0,0)

puts ret_str
Run Code Online (Sandbox Code Playgroud)
  • (3)运行。结果给出了所需的字符串。

完毕!