From: Daniel Berger Date: 2010-01-14T00:53:27+09:00 Subject: Re: ffi, kerberos On Jan 12, 6:52 pm, Heesob Park wrote: > 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 This almost got me there. I had to modify it somewhat to account for the fact that I'm on Snow Leopard (x64), so I replaced :uint with :long, 4 with 8 and ptr.read_int with ptr.read_long. Now I need to figure out how to create an FFI::MemoryPointer without necessarily knowing the size of the first argument. Thanks for the help! Regards, Dan