From: Heesob Park Date: 2010-01-13T10:52:12+09:00 Subject: Re: ffi, kerberos Hi, 2010/1/13 Daniel Berger : > Hi, > > I'm trying to wrap two function calls from kerberos, krb5_init_context > and krb5_free_context. Here are the prototypes for both: > > krb5_init_context(krb5_context * context) => krb5_error_code > krb5_free_context(krb5_context context) => void > > krb5_context is a struct, but unfortunately I don't know what its > members are. > > From the docs: > >     The krb5_context structure is designed to hold all per thread > state. All >     global variables that are context specific are stored in this > structure, >     including default encryption types, credentials-cache (ticket > file), and >     default realms. > >     The internals of the structure should never be accessed directly, > func- >     tions exist for extracting information. > > All I know is that it's 8 bytes in size. > > I tried something like this, but it didn't work: > > require 'ffi' > > module Krb5 >  class Context >    extend FFI::Library > >    class Error < StandardError; end > >    ffi_lib 'krb5' > >    attach_function :krb5_init_context, [:string], :uint >    attach_function :krb5_free_context, [:string], :void > >    def initialize >      @ctx = FFI::MemoryPointer.new(:pointer, 8) >      ret = krb5_init_context(@ctx) > >      if ret > 0 >        raise Error, "krb5_init_context() failed" >      end > >      if block_given? >        begin >          yield self >        ensure >          free >        end >      end >    end > >    def free >      krb5_free_context(@ctx) >    end >  end > end > > k = Krb5::Context.new > k.free > > I can use a plain string buffer, but then it segfaults on the 'free' > call. > > Any suggestions? > In my test platform, sizeof(krb5_context) is 4. Here is a working code: require 'ffi' module Krb5 class Context extend FFI::Library class Error < StandardError; end ffi_lib 'krb5' attach_function :krb5_init_context, [:pointer], :uint attach_function :krb5_free_context, [:uint], :void def initialize ptr = FFI::MemoryPointer.new(:char, 4) ret = krb5_init_context(ptr) if ret > 0 raise Error, "krb5_init_context() failed" end @ctx = ptr.read_int if block_given? begin yield self ensure free end end end def free krb5_free_context(@ctx) end end end k = Krb5::Context.new k.free Regards, Park Heesob