Module: NNG::FFI

Extended by:
FFI::Library
Defined in:
lib/nng/ffi.rb

Overview

FFI bindings for libnng

Defined Under Namespace

Classes: NngCtx, NngDialer, NngListener, NngPipe, NngSockaddr, NngSockaddrIn, NngSockaddrIn6, NngSockaddrInproc, NngSockaddrPath, NngSockaddrStorage, NngSocket

Constant Summary collapse

NNG_MAJOR_VERSION =

NOTE: These are compile-time version constants for reference. Use nng_version() to get the actual runtime library version.

1
NNG_MINOR_VERSION =
8
NNG_PATCH_VERSION =
0
NNG_MAXADDRLEN =

Maximum address length

128
NNG_OK =

Error codes

0
NNG_EINTR =
1
NNG_ENOMEM =
2
NNG_EINVAL =
3
NNG_EBUSY =
4
NNG_ETIMEDOUT =
5
NNG_ECONNREFUSED =
6
NNG_ECLOSED =
7
NNG_EAGAIN =
8
NNG_ENOTSUP =
9
NNG_EADDRINUSE =
10
NNG_ESTATE =
11
NNG_ENOENT =
12
NNG_EPROTO =
13
NNG_EUNREACHABLE =
14
NNG_EADDRINVAL =
15
NNG_EPERM =
16
NNG_EMSGSIZE =
17
NNG_ECONNABORTED =
18
NNG_ECONNRESET =
19
NNG_ECANCELED =
20
NNG_ENOFILES =
21
NNG_ENOSPC =
22
NNG_EEXIST =
23
NNG_EREADONLY =
24
NNG_EWRITEONLY =
25
NNG_ECRYPTO =
26
NNG_EPEERAUTH =
27
NNG_ENOARG =
28
NNG_EAMBIGUOUS =
29
NNG_EBADTYPE =
30
NNG_ECONNSHUT =
31
NNG_EINTERNAL =
1000
NNG_FLAG_ALLOC =

Flags

1
NNG_FLAG_NONBLOCK =

Allocate receive buffer

2
NNG_AF_UNSPEC =

Socket address families

0
NNG_AF_INPROC =
1
NNG_AF_IPC =
2
NNG_AF_INET =
3
NNG_AF_INET6 =
4
NNG_AF_ZT =
5
NNG_AF_ABSTRACT =
6
NNG_PIPE_EV_ADD_PRE =

Pipe events

0
NNG_PIPE_EV_ADD_POST =
1
NNG_PIPE_EV_REM_POST =
2
NNG_PIPE_EV_NUM =
3

Class Method Summary collapse

Class Method Details

.build_lib_pathsObject

Build library search paths with priority order:

  1. ENV - Direct path to library file

  2. ENV - Directory containing library

  3. Install config (from gem install –with-nng-*)

  4. Bundled library

  5. System default paths



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/nng/ffi.rb', line 37

def self.build_lib_paths
  paths = []
  platform = platform_info

  # Priority 1: Direct library path from environment
  if ENV['NNG_LIB_PATH'] && !ENV['NNG_LIB_PATH'].empty?
    paths << ENV['NNG_LIB_PATH']
    puts "NNG: Using library from NNG_LIB_PATH: #{ENV['NNG_LIB_PATH']}" if ENV['NNG_DEBUG']
  end

  # Priority 2: Library directory from environment
  if ENV['NNG_LIB_DIR'] && !ENV['NNG_LIB_DIR'].empty?
    dir = ENV['NNG_LIB_DIR']
    # Search for platform-specific library files in the directory
    Dir.glob(File.join(dir, platform[:lib_pattern])).each { |lib| paths << lib }
    puts "NNG: Searching in NNG_LIB_DIR: #{dir}" if ENV['NNG_DEBUG']
  end

  # Priority 3: Install-time configuration
  if @install_config[:nng_lib]
    paths << @install_config[:nng_lib]
    puts "NNG: Using library from install config: #{@install_config[:nng_lib]}" if ENV['NNG_DEBUG']
  elsif @install_config[:nng_dir]
    nng_dir = @install_config[:nng_dir]
    # Try common subdirectories based on platform
    subdirs = case platform[:os]
              when :windows
                %w[bin lib]
              when :macos
                %w[lib]
              else
                %w[lib lib64 lib/x86_64-linux-gnu]
              end

    subdirs.each do |subdir|
      lib_dir = File.join(nng_dir, subdir)
      Dir.glob(File.join(lib_dir, platform[:lib_pattern])).each { |lib| paths << lib }
    end
    puts "NNG: Searching in install config dir: #{nng_dir}" if ENV['NNG_DEBUG']
  end

  # Priority 4: Bundled library (platform-specific)
  bundled_libs = case platform[:os]
                 when :windows
                   [
                     File.expand_path('../../ext/nng/nng.dll', __dir__),
                     File.expand_path('../../ext/nng/libnng.dll', __dir__)
                   ]
                 when :macos
                   [
                     File.expand_path('../../ext/nng/libnng.1.11.0.dylib', __dir__),
                     File.expand_path('../../ext/nng/libnng.dylib', __dir__)
                   ]
                 else
                   [
                     File.expand_path('../../ext/nng/libnng.so.1.11.0', __dir__),
                     File.expand_path('../../ext/nng/libnng.so', __dir__)
                   ]
                 end
  paths += bundled_libs

  # Priority 5: System default paths (platform-specific)
  case platform[:os]
  when :windows
    # Windows: check common DLL locations
    paths += [
      File.join(ENV['WINDIR'] || 'C:/Windows', 'System32/nng.dll'),
      File.join(ENV['ProgramFiles'] || 'C:/Program Files', 'nng/bin/nng.dll')
    ]
  when :macos
    # macOS: check common library locations
    paths += [
      '/usr/local/lib/libnng.dylib',
      '/opt/homebrew/lib/libnng.dylib',
      '/usr/lib/libnng.dylib'
    ]
  else
    # Linux: check common library locations
    paths += [
      '/usr/local/lib/libnng.so',
      '/usr/lib/libnng.so',
      '/usr/lib/x86_64-linux-gnu/libnng.so',
      '/usr/lib/aarch64-linux-gnu/libnng.so'
    ]
  end

  paths.uniq
end

.check_error(ret, operation = "NNG operation") ⇒ Object

Check error code and raise exception if not OK

Raises:



477
478
479
480
481
# File 'lib/nng/ffi.rb', line 477

def self.check_error(ret, operation = "NNG operation")
  return if ret == NNG_OK
  error_msg = nng_strerror(ret)
  raise NNG::Error, "#{operation} failed: #{error_msg} (code: #{ret})"
end

.ctx_initializerObject

Create initialized context



499
500
501
# File 'lib/nng/ffi.rb', line 499

def self.ctx_initializer
  NngCtx.new.tap { |c| c[:id] = 0 }
end

.dialer_initializerObject

Create initialized dialer



489
490
491
# File 'lib/nng/ffi.rb', line 489

def self.dialer_initializer
  NngDialer.new.tap { |d| d[:id] = 0 }
end

.install_configObject



160
161
162
# File 'lib/nng/ffi.rb', line 160

def self.install_config
  @install_config
end

.listener_initializerObject

Create initialized listener



494
495
496
# File 'lib/nng/ffi.rb', line 494

def self.listener_initializer
  NngListener.new.tap { |l| l[:id] = 0 }
end

.loaded_lib_pathObject



156
157
158
# File 'lib/nng/ffi.rb', line 156

def self.loaded_lib_path
  @loaded_lib_path
end

.pipe_initializerObject

Create initialized pipe



504
505
506
# File 'lib/nng/ffi.rb', line 504

def self.pipe_initializer
  NngPipe.new.tap { |p| p[:id] = 0 }
end

.platform_infoObject

Detect platform and return library file patterns



20
21
22
23
24
25
26
27
28
29
# File 'lib/nng/ffi.rb', line 20

def self.platform_info
  case RbConfig::CONFIG['host_os']
  when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
    { os: :windows, lib_pattern: 'nng*.dll', lib_name: 'nng.dll' }
  when /darwin|mac os/
    { os: :macos, lib_pattern: 'libnng*.dylib', lib_name: 'libnng.dylib' }
  else
    { os: :linux, lib_pattern: 'libnng.so*', lib_name: 'libnng.so' }
  end
end

.socket_initializerObject

Create initialized socket



484
485
486
# File 'lib/nng/ffi.rb', line 484

def self.socket_initializer
  NngSocket.new.tap { |s| s[:id] = 0 }
end