Computer >> कंप्यूटर >  >> प्रोग्रामिंग >> Ruby

रूबी से फिडल के माध्यम से किसी भी सी पुस्तकालय का प्रयोग करें - रूबी मानक पुस्तकालय सबसे अच्छा गुप्त रखा जाता है।

फिडल एक अल्पज्ञात मॉड्यूल है जिसे रूबी के मानक पुस्तकालय में 1.9.x में जोड़ा गया था। यह आपको रूबी से सी पुस्तकालयों के साथ सीधे बातचीत करने की अनुमति देता है। यहां तक ​​कि यह आपको रूबी दुभाषिया के चलने पर उसका निरीक्षण और परिवर्तन करने देता है।

यह एक लोकप्रिय सी लाइब्रेरी libffi को लपेटकर काम करता है जो एक भाषा में लिखे गए कोड को दूसरी भाषा में लिखे गए तरीकों को कॉल करने की अनुमति देता है। यदि आपने इसके बारे में नहीं सुना है, तो "ffi" का अर्थ "विदेशी फ़ंक्शन इंटरफ़ेस" है। और आप केवल सी तक ही सीमित नहीं हैं। एक बार जब आप फिडल सीख जाते हैं, तो आप रस्ट और अन्य भाषाओं में लिखी गई पुस्तकालयों का उपयोग कर सकते हैं जो इसका समर्थन करती हैं।

आइए एक नजर डालते हैं फिडल पर। हम एक साधारण उदाहरण के साथ शुरुआत करेंगे और फिर एक सीरियल पोर्ट पर एक Arduino तक पहुंच कर समाप्त करेंगे। आपको इतना जानने की जरूरत नहीं है सी। मैं वादा करता हूँ। :)

एक साधारण उदाहरण

सादे पुराने रूबी में, आपको इसे कॉल करने से पहले हमेशा एक विधि को परिभाषित करना होगा। फिडल के साथ भी ऐसा ही है। आप सीधे सी फ़ंक्शन को कॉल नहीं कर सकते हैं। इसके बजाय आपको सी फ़ंक्शन के लिए एक रैपर बनाना होगा, फिर रैपर को कॉल करना होगा।

नीचे दिए गए उदाहरण में, हम 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)

इसे सुंदर बनाना

पिछला उदाहरण काम करता है, लेकिन यह एक तरह की क्रिया है। मुझे यकीन है कि आप कल्पना कर सकते हैं कि अगर आपको 100 कार्यों को लपेटना पड़ा तो चीजें कितनी अव्यवस्थित हो जाएंगी। इसलिए Fiddle एक अच्छा DSL प्रदान करता है। इसे 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 तरीके हमें सीरियल इनपुट को ग्रैन्युलैरिटी के स्तर के साथ कॉन्फ़िगर करने की अनुमति नहीं देते हैं।

सौभाग्य से, सी मानक पुस्तकालय सीरियल पोर्ट के साथ काम करने के लिए आवश्यक सभी कार्य प्रदान करता है। और फिडल का उपयोग करके, हम रूबी में इन सी कार्यों को एक्सेस कर सकते हैं।

बेशक, पहले से ही ऐसे रत्न हैं जो आपके लिए ऐसा करते हैं। जब मैं इस कोड पर काम कर रहा था तो मैंने रूबीसीरियल मणि से थोड़ी प्रेरणा ली। लेकिन हमारा लक्ष्य यह सीखना है कि यह काम खुद कैसे करें।

परीक्षा  termios.h

सी में, .h में समाप्त होने वाला कोई भी फ़ाइल नाम एक हेडर फ़ाइल है। इसमें उन सभी कार्यों और स्थिरांकों की एक सूची है जो पुस्तकालय तृतीय पक्ष कोड (हमारा कोड) को उपलब्ध कराता है। किसी भी सी लाइब्रेरी को लपेटने में पहला कदम इस फाइल को ढूंढना, इसे खोलना और चारों ओर देखना है।

हम जिस पुस्तकालय का उपयोग कर रहे हैं उसे टर्मियोस कहा जाता है। OSX Yosemite पर, हेडर फ़ाइल /usr/include/sys/termios.h पर स्थित होती है। यह linux पर कहीं और होगा।

यहाँ क्या 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"

संरचनाएं

सी में कक्षाएं या मॉड्यूल नहीं हैं। यदि आप चर के एक समूह को एक साथ समूहित करना चाहते हैं, तो आप एक संरचना का उपयोग करते हैं। रूबी में स्ट्रक्चर्स के साथ काम करने के लिए फिडल एक अच्छा मैकेनिज्म प्रदान करता है।

पहला कदम फिडल आयातक में संरचना को परिभाषित करना है। जैसा कि आप देख सकते हैं, हम हेडर फ़ाइल से कॉपी और पेस्ट करने में लगभग सक्षम हैं।

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',
]

अब हम मॉलोक विधि का उपयोग करके संरचना का "उदाहरण" बना सकते हैं। हम मानों को उसी तरह सेट और पुनर्प्राप्त कर सकते हैं जैसे हम किसी भी सामान्य रूबी क्लास इंस्टेंस के साथ करते हैं।

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

लाइब्रेरी का उपयोग करना

नीचे दिए गए उदाहरण में हम अपने सीरियल डिवाइस को रूबी में खोलते हैं, फिर उसका फाइल डिस्क्रिप्टर प्राप्त करते हैं। हम पढ़ने के लिए डिवाइस को कॉन्फ़िगर करने के लिए अपने टर्मियो फ़ंक्शन का उपयोग करते हैं। फिर हम पढ़ते हैं।

मैं यहाँ कुछ जादुई संख्याओं का उपयोग कर रहा हूँ। ये बिटवाइज़ कॉन्फ़िगरेशन विकल्पों के एक समूह के संयोजन का परिणाम हैं जो कि arduino के साथ संचार के लिए आवश्यक हैं। यदि आप रुचि रखते हैं कि जादुई संख्याएँ कहाँ से आती हैं, तो इस ब्लॉग पोस्ट को देखें।

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

सीरियल रीडर एक्शन में है

अगर मैं अब अपने arduino को एक प्रोग्राम के साथ लोड करता हूं जो लगातार हैलो वर्ल्ड प्रिंट करता है, तो मैं इसे पढ़ने के लिए अपनी रूबी स्क्रिप्ट का उपयोग कर सकता हूं।

रूबी से फिडल के माध्यम से किसी भी सी पुस्तकालय का प्रयोग करें - रूबी मानक पुस्तकालय सबसे अच्छा गुप्त रखा जाता है। यह arduino प्रोग्राम सीरियल को बार-बार "हैलो वर्ल्ड" लिखता है

और जब मैं अपना सीरियल मॉनीटर चलाता हूं तो यह कैसा दिखता है।

रूबी से फिडल के माध्यम से किसी भी सी पुस्तकालय का प्रयोग करें - रूबी मानक पुस्तकालय सबसे अच्छा गुप्त रखा जाता है।


  1. रूबी का उपयोग कैसे करें कोई भी, सभी, कोई नहीं और एक

    आज आप 4 एन्यूमरेबल विधियों के बारे में जानेंगे जो आपको तत्वों की एक सरणी, एक हैश, या किसी अन्य ऑब्जेक्ट के खिलाफ सशर्त स्टेटमेंट की जांच करने में मदद करेंगे जिसमें एन्यूमरेबल मॉड्यूल शामिल है। ये 4 विधियाँ या तो true लौटाती हैं या false । सामग्री 1 रूबी ऑल मेथड 2 सभी और खाली सरणी 3 रूबी कोई नही

  1. रूबी ग्रेप विधि का उपयोग कैसे करें (उदाहरण के साथ)

    आइए बात करते हैं grep . के बारे में विधि। यह विधि आपके लिए क्या कर सकती है? आप ग्रेप का उपयोग एरेज़ और रेंज जैसी असंख्य वस्तुओं को फ़िल्टर करने के लिए कर सकते हैं। “लेकिन चुनें पहले से ही ऐसा करता है!” हां, लेकिन grep एक अलग तरीके से काम करता है और यह अलग परिणाम देता है। आइए कुछ उदाहरण देखें।

  1. रूबी मानचित्र विधि का उपयोग कैसे करें (उदाहरण के साथ)

    मैप एक रूबी विधि है जिसका उपयोग आप ऐरे, हैश और रेंज के साथ कर सकते हैं। मानचित्र का मुख्य उपयोग डेटा को ट्रांसफ़ॉर्म करना है। उदाहरण के लिए : स्ट्रिंग्स की एक सरणी को देखते हुए, आप प्रत्येक स्ट्रिंग पर जा सकते हैं और प्रत्येक वर्ण को अपरकेस बना सकते हैं। या यदि आपके पास User . की सूची है ऑब्जेक्