কম্পিউটার

Fiddle এর মাধ্যমে রুবি থেকে যেকোন সি লাইব্রেরি ব্যবহার করুন - রুবি স্ট্যান্ডার্ড লাইব্রেরিগুলো সবচেয়ে ভালোভাবে গোপন রাখা হয়।

ফিডল হল একটি স্বল্প পরিচিত মডিউল যা 1.9.x এ রুবির স্ট্যান্ডার্ড লাইব্রেরিতে যোগ করা হয়েছিল। এটি আপনাকে রুবি থেকে সি লাইব্রেরির সাথে সরাসরি যোগাযোগ করতে দেয়। এমনকি এটি আপনাকে রুবি দোভাষীকে পরিদর্শন ও পরিবর্তন করতে দেয় এটি চলার সাথে সাথে৷

এটি একটি জনপ্রিয় সি লাইব্রেরি libffi মোড়ানোর মাধ্যমে কাজ করে যা একটি ভাষায় লিখিত কোডকে অন্য ভাষায় লিখিত পদ্ধতিকে কল করার অনুমতি দেয়। যদি আপনি এটির কথা না শুনে থাকেন, "ffi" মানে "বিদেশী ফাংশন ইন্টারফেস"। এবং আপনি শুধু সি-তে সীমাবদ্ধ নন। একবার আপনি ফিডল শিখলে, আপনি রাস্ট এবং এটি সমর্থনকারী অন্যান্য ভাষায় লেখা লাইব্রেরি ব্যবহার করতে পারেন।

চলুন বাঁশি কটাক্ষপাত করা যাক. আমরা একটি সাধারণ উদাহরণ দিয়ে শুরু করব এবং তারপর একটি সিরিয়াল পোর্টের মাধ্যমে একটি Arduino অ্যাক্সেস করে শেষ করব। তোমার এতটা জানার দরকার নেই C. আমি কথা দিচ্ছি। :)

একটি সাধারণ উদাহরণ

সাধারণ-পুরাতন রুবিতে, আপনি কল করার আগে আপনাকে সর্বদা একটি পদ্ধতি সংজ্ঞায়িত করতে হবে। এটি ফিডলের সাথে একই। আপনি সরাসরি একটি সি ফাংশন কল করতে পারবেন না। পরিবর্তে আপনাকে C ফাংশনের জন্য একটি র‍্যাপার তৈরি করতে হবে, তারপর র‍্যাপারটিকে কল করুন৷

নীচের উদাহরণে, আমরা C এর লগারিদম ফাংশন মোড়ানো করছি। আমরা মূলত রুবির Math.log নকল করছি .

require 'fiddle'

# We're going to "open" a library, so we have to tell Fiddle where
# it's located on disk. This example works on OSX Yosemite.
libm = Fiddle.dlopen('/usr/lib/libSystem.dylib')


# Create a wrapper for the c function "log". 
log = Fiddle::Function.new(
  libm['log'],            # Get the function from the math library we opened
  [Fiddle::TYPE_DOUBLE],  # It has one argument, a double, which is similar to ruby's Float
  Fiddle::TYPE_DOUBLE     # It returns a double
)

# call the c function via our wrapper
puts log.call(3.14159)

এটিকে সুন্দর করা

পূর্ববর্তী উদাহরণ কাজ করে, কিন্তু এটা verbose ধরনের. আমি নিশ্চিত যে আপনি যদি 100টি ফাংশন মোড়ানো হয় তবে আপনি কীভাবে বিশৃঙ্খল জিনিসগুলি পাবেন তা কল্পনা করতে পারেন। এই কারণেই ফিডল একটি চমৎকার ডিএসএল প্রদান করে। এটি Fiddle::Importer এর মাধ্যমে প্রকাশ করা হয়েছে মিক্সিং।

এই মিক্সিনটি ব্যবহার করে বাহ্যিক ফাংশনে পূর্ণ একটি মডিউল তৈরি করা ছোট কাজ করে। নীচের উদাহরণে, আমরা একটি মডিউল তৈরি করছি যাতে বেশ কয়েকটি লগারিদম পদ্ধতি রয়েছে।

require 'fiddle'
require 'fiddle/import'

module Logs
  extend Fiddle::Importer
  dlload '/usr/lib/libSystem.dylib'
  extern 'double log(double)'
  extern 'double log10(double)'
  extern 'double log2(double)'
end

# We can call the external functions as if they were ruby methods!
puts Logs.log(10)   # 2.302585092994046
puts Logs.log10(10) # 1.0
puts Logs.log2(10)  # 3.321928094887362

সিরিয়াল পোর্ট নিয়ন্ত্রণ করা হচ্ছে

ঠিক আছে, তাই আপনি অবশেষে সেই Arduinosগুলির মধ্যে একটি কিনেছেন যা আপনি বছরের পর বছর ধরে কেনার কথা ভাবছেন। আপনি সিরিয়াল পোর্ট ব্যবহার করে প্রতি সেকেন্ডে একবার আপনার কম্পিউটারে "হ্যালো ওয়ার্ল্ড" পাঠ্য পাঠাচ্ছেন।

এখন, আপনি যদি রুবি ব্যবহার করে সেই ডেটা পড়তে পারেন তবে এটি সত্যিই সুন্দর হবে। এবং আপনি আসলে রুবির স্ট্যান্ডার্ড আইও পদ্ধতি ব্যবহার করে সিরিয়াল পোর্ট থেকে পড়তে পারেন। কিন্তু এই IO পদ্ধতিগুলি আমাদেরকে হার্ডকোর হার্ডওয়্যার হ্যাকার হতে হলে আমাদের প্রয়োজনীয় গ্রানুলিটি স্তরের সাথে সিরিয়াল ইনপুট কনফিগার করতে দেয় না৷

সৌভাগ্যবশত, সি স্ট্যান্ডার্ড লাইব্রেরি সিরিয়াল পোর্টের সাথে কাজ করার জন্য আমাদের প্রয়োজনীয় সমস্ত ফাংশন সরবরাহ করে। এবং ফিডল ব্যবহার করে, আমরা রুবিতে এই সি ফাংশনগুলি অ্যাক্সেস করতে পারি।

অবশ্যই, ইতিমধ্যে এমন রত্ন রয়েছে যা আপনার জন্য এটি করে। আমি যখন এই কোডে কাজ করছিলাম তখন আমি রুবাইসিরিয়াল মণি থেকে একটু অনুপ্রেরণা নিয়েছিলাম। কিন্তু আমাদের লক্ষ্য হল কীভাবে এই জিনিসগুলি নিজেরাই করতে হয় তা শিখতে হবে৷

টার্মিওস পরীক্ষা করা হচ্ছে।

C-তে, .h দিয়ে শেষ হওয়া যেকোনো ফাইলের নাম একটি হেডার ফাইল। এটিতে সমস্ত ফাংশন এবং ধ্রুবকগুলির একটি তালিকা রয়েছে যা লাইব্রেরি তৃতীয় পক্ষের কোডে (আমাদের কোড) উপলব্ধ করে। যেকোন সি লাইব্রেরি মোড়ানোর প্রথম ধাপ হল এই ফাইলটি খুঁজে বের করা, এটি খুলুন এবং চারপাশে তাকান৷

আমরা যে লাইব্রেরিটি ব্যবহার করছি তার নাম টার্মিওস। OSX Yosemite-এ, হেডার ফাইলটি /usr/include/sys/termios.h-এ অবস্থিত। এটি লিনাক্সে অন্য কোথাও থাকবে।

এখানে termios.h এর মত দেখায়। আমি স্পষ্টতার জন্য এটিকে কিছুটা ঘনীভূত করেছি।

typedef unsigned long   tcflag_t;
typedef unsigned char   cc_t;
typedef unsigned long   speed_t;

struct termios {
    tcflag_t    c_iflag;    /* input flags */
    tcflag_t    c_oflag;    /* output flags */
    tcflag_t    c_cflag;    /* control flags */
    tcflag_t    c_lflag;    /* local flags */
    cc_t        c_cc[NCCS]; /* control chars */
    speed_t     c_ispeed;   /* input speed */
    speed_t     c_ospeed;   /* output speed */
};


int tcgetattr(int, struct termios *);
int tcsetattr(int, int, const struct termios *);
int tcflush(int, int);

এই কোড সম্পর্কে লক্ষ্য করার জন্য তিনটি গুরুত্বপূর্ণ বিষয় রয়েছে। প্রথমত, আমাদের কিছু টাইপডেফ আছে। তারপরে আমাদের কাছে একটি ডেটা কাঠামো রয়েছে যা সংযোগের জন্য কনফিগারেশন তথ্য ধরে রাখতে ব্যবহৃত হয়। অবশেষে, আমাদের কাছে পদ্ধতি আছে, আমরা ব্যবহার করতে যাচ্ছি।

বেহালার আমদানিকারক ব্যবহার করে, আমরা প্রায় এই বিভাগগুলিকে আমাদের রুবি কোডে কপি করতে পারি। আসুন একে একে মোকাবেলা করি।

টাইপ উপনাম এবং typedefs

সি-তে ডেটা টাইপের জন্য উপনাম তৈরি করা খুবই সাধারণ। উদাহরণস্বরূপ, termios.h ফাইলটি speed_t নামে একটি নতুন প্রকার তৈরি করে যা একটি দীর্ঘ পূর্ণসংখ্যা। ফিডল আমদানিকারক তার টাইপলিয়াস বৈশিষ্ট্যের মাধ্যমে এগুলি পরিচালনা করতে সক্ষম৷

# equivalent to `typedef unsigned long tcflag_t;`
typealias "tcflag_t", "unsigned long"

কাঠামো

C এর কোনো ক্লাস বা মডিউল নেই। আপনি যদি একগুচ্ছ ভেরিয়েবলকে একসাথে গ্রুপ করতে চান তবে আপনি একটি struct ব্যবহার করেন। ফিডল রুবিতে স্ট্রাকটগুলির সাথে কাজ করার জন্য একটি চমৎকার প্রক্রিয়া প্রদান করে।

প্রথম ধাপ হল ফিডল ইম্পোর্টারে স্ট্রাকচার সংজ্ঞায়িত করা। আপনি দেখতে পাচ্ছেন, আমরা প্রায় হেডার ফাইল থেকে কপি এবং পেস্ট করতে সক্ষম।

Termios = struct [
  'tcflag_t c_iflag',
  'tcflag_t c_oflag',
  'tcflag_t c_cflag',
  'tcflag_t c_lflag',
  'cc_t         c_cc[20]',
  'speed_t  c_ispeed',
  'speed_t  c_ospeed',
]

এখন আমরা malloc পদ্ধতি ব্যবহার করে struct এর একটি "উদাহরণ" তৈরি করতে পারি। আমরা যেকোন সাধারণ রুবি ক্লাস ইন্সট্যান্সের মতো একইভাবে মান সেট এবং পুনরুদ্ধার করতে পারি।

s = Termios.malloc
s.c_iflag = 12345

এটি সব একসাথে রাখা

আপনি যদি টাইপডেফ এবং স্ট্রাকস সম্পর্কে আমরা যা শিখেছি তার সাথে আমরা ইতিমধ্যে ফাংশনগুলির সাথে যা প্রদর্শন করেছি তা একত্রিত করলে, আমরা টার্মিওস লাইব্রেরির একটি কার্যকরী মোড়ক একসাথে রাখতে পারি।

সিরিয়াল পোর্ট কনফিগার করার জন্য আমাদের প্রয়োজনীয় পদ্ধতিগুলি আমাদের মোড়কে রয়েছে। আমরা বাকি জন্য সাধারণ পুরানো রুবি ব্যবহার করব।

require 'fiddle'
require 'fiddle/import'

# Everything in this module was pretty much copied directly from 
# termios.h. In Yosemite it's at /usr/include/sys/termios.h
module Serial
  extend Fiddle::Importer
  dlload '/usr/lib/libSystem.dylib'

  # Type definitions
  typealias "tcflag_t", "unsigned long"
  typealias "speed_t", "unsigned long"
  typealias "cc_t", "char"

  # A structure which will hold configuratin data. Instantiate like
  # so: `Serial::Termios.malloc()`
  Termios = struct [
    'tcflag_t   c_iflag',
    'tcflag_t   c_oflag',
    'tcflag_t   c_cflag',
    'tcflag_t   c_lflag',
    'cc_t         c_cc[20]',
    'speed_t    c_ispeed',
    'speed_t    c_ospeed',
  ]

  # Functions for working with a serial device
  extern 'int   tcgetattr(int, struct termios*)'       # get the config for a serial device
  extern 'int   tcsetattr(int, int, struct termios*)'  # set the config for a serial device
  extern 'int   tcflush(int, int)'                     # flush all buffers in the device

end

লাইব্রেরি ব্যবহার করা

নীচের উদাহরণে আমরা আমাদের সিরিয়াল ডিভাইসটি রুবিতে খুলি, তারপর এটির ফাইল বর্ণনাকারী পাই। আমরা পড়ার জন্য ডিভাইস কনফিগার করতে আমাদের টার্মিওস ফাংশন ব্যবহার করি। তারপর আমরা পড়ি।

আমি এখানে কিছু ম্যাজিক সংখ্যা ব্যবহার করছি। এগুলি বিটওয়াইজ কনফিগারেশন বিকল্পগুলির একটি গুচ্ছ একত্রিত করার ফলাফল যা আরডুইনোর সাথে যোগাযোগের জন্য প্রয়োজনীয়। আপনি যদি আগ্রহী হন যে ম্যাজিক নম্বরগুলি কোথা থেকে এসেছে, এই ব্লগ পোস্টটি দেখুন৷

file = open("/dev/cu.wchusbserial1450", 'r')
fd = file.to_i

# Create a new instance of our config structure
config = Serial::Termios.malloc

# Load the default config options into our struct
Serial.tcgetattr(fd, config);

# Set config options important to the arduino. 
# I'm sorry for the magic numbers. 
config.c_ispeed = 9600;
config.c_ospeed = 9600;
config.c_cflag = 51968;
config.c_iflag = 0;
config.c_oflag = 0;

# wait for 12 characters to come in before read returns.
config.c_cc[17] = 12;
# no minimum time to wait before read returns 
config.c_cc[16] = 0;

# Save our configuration
Serial.tcsetattr(fd, 0, config);

# Wait 1 second for the arduino to reboot
sleep(1)

# Remove any existing serial input waiting to be read
Serial.tcflush(fd, 1)

buffer = file.read(12)
puts "#{ buffer.size } bytes: #{ buffer }"

file.close

অ্যাকশনে সিরিয়াল রিডার

যদি আমি এখন আমার আরডুইনোকে এমন একটি প্রোগ্রামের সাথে লোড করি যা হ্যালো ওয়ার্ল্ডকে ক্রমাগত প্রিন্ট করে, আমি এটি পড়ার জন্য আমার রুবি স্ক্রিপ্ট ব্যবহার করতে পারি৷

Fiddle এর মাধ্যমে রুবি থেকে যেকোন সি লাইব্রেরি ব্যবহার করুন - রুবি স্ট্যান্ডার্ড লাইব্রেরিগুলো সবচেয়ে ভালোভাবে গোপন রাখা হয়। এই arduino প্রোগ্রামটি বারবার সিরিয়ালে "হ্যালো ওয়ার্ল্ড" লিখেছে

এবং আমি যখন আমার সিরিয়াল মনিটর চালাই তখন এটি কেমন দেখায়।

Fiddle এর মাধ্যমে রুবি থেকে যেকোন সি লাইব্রেরি ব্যবহার করুন - রুবি স্ট্যান্ডার্ড লাইব্রেরিগুলো সবচেয়ে ভালোভাবে গোপন রাখা হয়।


  1. রুবি আলিয়াস কীওয়ার্ড কীভাবে ব্যবহার করবেন

  2. রুবি এনি, অল, নন এবং ওয়ান কিভাবে ব্যবহার করবেন

  3. রুবি গ্রেপ পদ্ধতি কীভাবে ব্যবহার করবেন (উদাহরণ সহ)

  4. রুবি মানচিত্র পদ্ধতি কীভাবে ব্যবহার করবেন (উদাহরণ সহ)