从内部红宝石调用C code - 如何使用返回的指针? [英] Calling C code from within Ruby -- How to use the returned pointer?

查看:106
本文介绍了从内部红宝石调用C code - 如何使用返回的指针?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题:

我想在我的Ruby程序使用一种算法,在C codeD,并通过DLL暴露。

我想对待算法作为一个黑盒子,我可以从内部调用红宝石 - 简单地传递所需的参数和使用结果

红宝石(包括1.8.7和1.9.3)有这似乎意在使其很容易与动态库接口到底该怎么做我的的Win32API 模块米后。

但问题是,我似乎无法得到的Win32API调用返回一个字符串。

详细内容:

第三方的C函数是 codeGEN()。它取6个参数,包括源串,任意字符串作为加密密钥,并且,为了简单起见,4数值参数,人们符号int一无符号长,和两个无符号短裤。从这些,codeGEN()实现一个黑箱算法返回结果字符串。

在C语言为codeGEN()是:

 为const char * codeGEN(INT encryp_level,
                     为const char * source_str,为const char * encryp_key,
                     无符号长param_a,
                     无符号短param_b,无符号短param_c
                  )

请注意,无论是输入字符串是常量,即它们提供给codeGEN()作为字符串 - 所以指向常量字符串

为codeGEN()的返回值也是一个字符串,固定的最大长度,所以它会返回一个指针。

我的问题:

我如何去C $ CGEN呼叫设定高达$()和取回它应该生成字符串?

我尝试:

下面简单的code给我的整数作为返回值,当我期待着获得一个字符串。

 要求'的Win32APIcodeGEN = Win32API.new(encrypt.dll,codeGEN,ISSIII,S)ret_str = codeGen.Call(3,富,酒吧,0,0,0)把ret_str

然而,而不是得到一个字符串返回,我回来一个整数。 修改:难道这是一个指针

虽然我在Windows 7上使用Ruby 1.9.3,64位版本,我还测试了上面在Windows XP,32位,并使用Ruby 1.8.7,所以我pretty肯定这件事情跟我的使用Win32API的本身。

不知道问题是出在任何这些:


  • 请整数(3,0,...)需要打包?

  • 请我需要短期和长期的类型之间的区别?

  • 我是不正确地处理的返回值?

  • 如果返回值是一个指针,我如何在Ruby中使用它?

  • 别的东西吗?

任何有识之士将是非常美联社preciated!


解决方案

虽然我不知道为什么的Win32API 办法没有工作,我发现一个更容易解决方案使用 FFI 从内部调用Ruby的C函数或DLL的接口的问题。


使用的解决方案 FFI

使用 FFI 在Ruby中与DLL的接口,如下:


  • (1)安装 FFI (适用于红宝石1.9.3,情况因人而异与previous版本)

    创业板安装FFI


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



 要求FFI模块$ C $#玺诚传媒包装红宝石(你的选择)
  延长FFI ::图书馆
  ffi_lib'codeGEN'#DLL名称(给)
  attach_function
        :CREATE_ code,#方法名(你的选择)
        :创建codeShort3,#DLL函数名(特定)
          [:INT,:字符串:字符串:UINT,:USHORT,:USHORT]:字符串
                          #指定C参数/返回值的类型
结束ret_str = codeGen.create_ code(3,富,酒吧,0,0,0)把ret_str



  • (3)运行。结果给出所希望的字符串。

完成!

Problem:

I'd like to use in my Ruby program an algorithm that is coded in C and exposed through a DLL.

I would like to treat the algorithm as a black box that I can call from within Ruby -- simply pass in the required parameters and use the result.

Ruby (both 1.8.7 and 1.9.3) has the Win32API module which seems intended to make it quite easy to interface with dynamic libraries to do exactly what I'm after.

But the problem is that I can't seem to get the Win32API call to send back a string.

Details:

The third-party C function is CodeGen(). It take 6 parameters, including a source string, an arbitrary string to serve as encryption key, and, for simplicity, 4 numerical parameters, one signed int, one unsigned long, and two unsigned shorts. From these, CodeGen() implements a black-box algorithm to return a resulting string.

The C prototype for CodeGen() is:

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
                  )

Note that both the input strings are constants, i.e. they are supplied to CodeGen() as strings -- so pointers to constant strings

The return value for CodeGen() is also a string, of fixed maximum length, so it will return a pointer.

My Question:

How do I go about setting up the call to CodeGen() and getting back the string it is supposed to generate?

My attempts:

The code below simply gives me integers as the return value, when I am expecting to obtain a string.

require 'Win32API'

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

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

puts ret_str

However, instead of getting a string back, I get back an integer. Edit: Could this be a pointer?

Although I'm using Ruby 1.9.3 on Windows 7, 64-bit edition, I've also tested the above on Windows XP, 32-bits, and using Ruby 1.8.7, so I'm pretty sure it's something to do with my use of the Win32API itself.

Not sure whether the problem is any of these:

  • do the integers (3, 0, ...) need to be packed?
  • do I need to distinguish between short and long types?
  • am I not properly handling the return value?
  • if the return value is a pointer, how do I use this in Ruby?
  • something else?

Any insight would be much appreciated!

解决方案

While I don't know why the Win32API approach did not work, I've found an easier solution using FFI to the problem of calling C functions from within Ruby or interfacing with DLLs.


Solution using FFI

Use FFI in Ruby for interfacing with DLLs, as follows:

  • (1) Install ffi (works with ruby 1.9.3, ymmv with previous versions)

    gem install ffi

  • (2) Create your own Ruby module to wrap the C function

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) Run. Result gives a string as desired.

Done!

这篇关于从内部红宝石调用C code - 如何使用返回的指针?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆