Можно ли сделать функцию прикрепленной с ruby ffi private?
У меня есть общий объект lib, к которому я присоединяю функции, используя ruby ffi. Я хочу прикрепить каждую функцию с псевдонимом и сделать псевдоним частным, потому что вызов их может быть опасным. Я обертываю каждую функцию в свою собственную функцию модуля ruby, вот быстрый пример:
module LibC
extend FFI::Library
ffi_lib FFI::Library::LIBC
attach_function :free, [:pointer], :void
end
module MyModule
class << self
extend FFI::Library
ffi_lib '../my_shared_lib.so'
def function(str)
is_string(str)
ptr = ffi_function(str)
result = String.new(ptr.read_string)
LibC.free(ptr)
result
end
private
# attach function
attach_function :ffi_function, :function, [:string], :pointer
def is_string(object)
unless object.kind_of? String
raise TypeError,
"Wrong argument type #{object.class} (expected String)"
end
end
end
end
Функция ffi_function
кажется, все еще может быть вызвано за пределами модуля. Как я могу сделать это полностью приватным?
1 ответ
Поместите функцию attach_function вне класса << self и добавьте private:ffi_function внутри себя.
Вот пример, адаптированный из некоторого другого кода. EnumProcesses - скрытая функция ffi_function, а process_ids - открытая оболочка.
require 'ffi'
module Win32
extend FFI::Library
ffi_lib 'Psapi'
ffi_convention :stdcall
=begin
BOOL WINAPI EnumProcesses(
_Out_ DWORD *pProcessIds,
_In_ DWORD cb,
_Out_ DWORD *pBytesReturned
);
=end
attach_function :EnumProcesses, [:pointer, :uint32, :pointer], :int
class << self
def process_ids
# Allocate room for the windows process ids.
windows_process_ids = FFI::MemoryPointer.new(:uint32, 1024)
# Allocate room for windows to tell us how many process ids there were.
bytes_returned = FFI::MemoryPointer.new(:uint32)
# Ask for the process ids
if EnumProcesses(windows_process_ids, windows_process_ids.size, bytes_returned) != 0
# Determine the number of ids we were given
process_ids_returned = bytes_returned.read_int / bytes_returned.size
# Pull all the ids out of the raw memory and into a local ruby array.
windows_process_ids.read_array_of_type(:uint32, :read_uint32, process_ids_returned)
end
end
# Hide EnumProcesses from the outside
private :EnumProcesses
end
end
Win32.process_ids # This will work
Win32.EnumProcesses # This throws an exception: private method `EnumProcesses' called for Win32:Module (NoMethodError)