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

问题:

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

我想把algorithm看作是一个黑盒子,我可以从Ruby中调用 – 只需传入所需的参数并使用结果即可。

Ruby(包括1.8.7和1.9.3)都有Win32API模块,这个模块看起来很容易与dynamic库进行交互,从而完成我之后的工作。

但问题是,我似乎无法获得Win32API调用发回一个string。

细节:

第三方的C函数是CodeGen() 。 它需要6个参数,包括一个源string,一个任意string作为encryption密钥,为简单起见,还有4个数字参数,一个有符号整数,一个无符号长整数和两个无符号短整数。 从这些CodeGen()实现一个黑盒algorithm返回一个结果string。

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 ) 

请注意,这两个inputstring都是常量,即它们作为string提供给CodeGen(),所以指向常量string

CodeGen()的返回值也是一个固定的最大长度的string,所以它会返回一个指针。

我的问题:

我如何去设置CodeGen()的调用,并找回它应该生成的string?

我的尝试:

下面的代码只是给我整数作为返回值,当我期望获得一个string。

 require 'Win32API' codeGen = Win32API.new("encrypt.dll", "CodeGen", "ISSIII", "S") ret_str = codeGen.Call(3, "foo", "bar", 0, 0, 0) puts ret_str 

但是,而不是得到一个string,我得到一个整数。 编辑:这可能是一个指针?

虽然我在Windows 7 64位版本上使用Ruby 1.9.3,但是我也在Windows XP(32位)上使用Ruby 1.8.7testing了上述内容,所以我很确定这是要做的事情与我使用Win32API本身。

不确定问题是否是这些中的任何一个:

  • 整数(3,0,…)是否需要打包?
  • 我需要区分短型还是长型?
  • 我没有正确处理返回值?
  • 如果返回值是一个指针,我该如何在Ruby中使用它?
  • 别的东西?

任何有识之士将不胜感激!

Solutions Collecting From Web of "在Ruby中调用C代码 – 如何使用返回的指针?"

虽然我不知道为什么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 
  • (3)运行。 结果根据需要提供一个字符串。

完成!