2009-02-25 11 views
10

मैं वर्तमान में पार मंच अनुप्रयोगों पर काम कर रहा हूँ और करने के लिए कैसे अन्य लोगों को इस तरह के रूप समस्याओं से निपटने के रूप में बस उत्सुक था:क्रॉस-प्लेटफ़ॉर्म विकास से निपटने का आपका पसंदीदा तरीका क्या है?

  • Endianess
  • चल बिन्दु समर्थन (कुछ सिस्टम, सॉफ्टवेयर में अनुकरण बहुत धीमी गति से)
  • आई/ओ सिस्टम (यानी डिस्प्ले, ध्वनि फ़ाइल का उपयोग, नेटवर्किंग, आदि)
  • और निश्चित रूप से, संकलक मतभेद की अधिकता

जाहिर है यह है सी/सी ++ जैसी भाषाओं में लक्षित जो इस सामान में से अधिकांश को अमूर्त नहीं करते हैं (जावा या सी # के विपरीत, जो कई प्रणालियों पर समर्थित नहीं हैं)।

और यदि आप उत्सुक थे, तो जिन सिस्टमों पर मैं विकास कर रहा हूं वे निंटेंडो डीएस, वाईआई, पीएस 3, एक्सबॉक्स 360 और पीसी हैं।


संपादित
यहाँ पर वास्तव में अच्छा जवाब, कैसे मतभेद खुद, पुस्तकालय सुझाव (यहां तक ​​कि बस में दे रही है और शराब का उपयोग करने का सुझाव) को संभालने के लिए से लेकर की एक बहुत कुछ किया गया है। मैं वास्तव में एक समाधान की तलाश नहीं कर रहा हूं (पहले से ही एक है), लेकिन यह सिर्फ उत्सुक था कि दूसरों को इस स्थिति से कैसे निपटना है क्योंकि यह देखना हमेशा अच्छा होता है कि दूसरों को कैसे लगता है/कोड ताकि आप विकसित हो सकें और बढ़ सकें।

यहां जिस तरह से मैंने समस्या का सामना किया है (और, यदि आपने ऊपर सिस्टम की इस सूची से अनुमान नहीं लगाया है, तो मैं कंसोल/विंडोज गेम विकसित कर रहा हूं)। कृपया ध्यान रखें कि जिन प्रणालियों पर मैं काम करता हूं उनमें आम तौर पर उनके लिए लिखे गए क्रॉस-प्लेटफार्म पुस्तकालय नहीं होते हैं (सोनी वास्तव में अनुशंसा करता है कि आप अपना खुद का प्रतिपादन इंजन स्क्रैच से लिखें और केवल उनके ओपनजीएल कार्यान्वयन का उपयोग करें, जो काफी नहीं है वैसे भी, एक संदर्भ के रूप में मानकों)।

Endianess
हमारे संपत्ति के सभी कस्टम प्रत्येक प्रणाली के लिए बनाया जा सकता है। हमारे सभी कच्चे डेटा (बनावट को छोड़कर) एक्सएमएल में संग्रहीत किया जाता है जिसे हम प्रोजेक्ट के निर्माण के दौरान सिस्टम विशिष्ट बाइनरी प्रारूप में परिवर्तित करते हैं। यह देखते हुए कि हम गेम कंसोल के लिए कैसे विकास कर रहे हैं, हमें विभिन्न एंडियन प्रारूपों के साथ प्लेटफ़ॉर्म के बीच स्थानांतरित होने के बारे में चिंता करने की आवश्यकता नहीं है (केवल पीसी उपयोगकर्ताओं को ऐसा करने की अनुमति देता है, इस प्रकार, यह अन्य प्रणालियों से भी इन्सुलेट किया जाता है) ।

चल बिन्दु समर्थन
सबसे आधुनिक प्रणालियों अंक मान ठीक चल रहा है, इसका अपवाद Nintendo DS है (और GBA, लेकिन काफी thats हमारे लिए इन दिनों एक मरे हुए मंच)। हम इसे 2 अलग-अलग वर्गों के माध्यम से संभालते हैं। पहला एक "निश्चित बिंदु" वर्ग (टेम्पलेटेड, निर्दिष्ट कर सकता है कि किस पूर्णांक प्रकार का उपयोग करना है और दशमलव मान के लिए कितने बिट्स) जो सभी अंकगणितीय ऑपरेटरों (बिट-शिफ्ट की देखभाल करना) लागू करता है और प्रकार रूपांतरणों को स्वचालित करता है। दूसरा एक "फ्लोटिंग पॉइंट" वर्ग है, जो मूल रूप से अधिकांश भाग के लिए फ्लोट के चारों ओर एक रैपर होता है, केवल अंतर यह है कि यह शिफ्ट ऑपरेटरों को भी लागू करता है। शिफ्ट ऑपरेटर को कार्यान्वित करके, हम डीएस पर तेजी से गुणा/डिवीजनों के लिए बिट शिफ्ट का उपयोग कर सकते हैं और फिर प्लेटफार्मों में सहजता से संक्रमण कर सकते हैं जो फ्लोट्स (एक्सबॉक्स 360 की तरह) के साथ बेहतर काम करते हैं।

आई/ओ सिस्टम
यह शायद हमारे लिए trickiest समस्या है क्योंकि हर प्रणाली नियंत्रक इनपुट, ग्राफिक्स (Xbox360, DirectX9 का एक संस्करण का उपयोग करता है PS3 ओपन है या आप अपने स्वयं लिख सकते हैं के लिए वहाँ खुद विधि है, स्क्रैच से और डीएस और वाईआई के पास अपनी खुद की मालिकाना प्रणाली है), ध्वनि और नेटवर्किंग (वास्तव में केवल डीएस प्रोटोकॉल में बहुत अलग है, लेकिन फिर उनमें से प्रत्येक का अपना सर्वर सिस्टम है जिसका उपयोग आप करना चाहते हैं)।

जिस तरह से हम इसे समाप्त कर रहे थे, वह बस प्रत्येक सिस्टम के लिए काफी उच्च स्तर के रैपर लिख रहा था (उदाहरण के लिए ग्राफिक्स के लिए मेष, नियंत्रकों के लिए कुंजी मैपिंग सिस्टम इत्यादि) और सभी सिस्टम एक ही शीर्षलेख फ़ाइलों का उपयोग करते हैं पहुंच। यह सिर्फ प्रत्येक मंच के लिए विशिष्ट सीपीपी फाइलों को लिखने का मामला है (इस प्रकार "इंजन" बना रहा है)।

संकलक मतभेद
यह एक बात है कि बहुत आसानी से घेरने की कोशिश नहीं की जा सकती, जैसा कि हम compilers के साथ समस्याओं में चलाने है हम आम तौर पर एक स्थानीय विकि पर लॉग जानकारी (ताकि दूसरों के लिए बाहर देखने के लिए क्या देख सकते हैं और इसके साथ जाने के लिए कामकाज) और यदि संभव हो, तो एक मैक्रो लिखें जो हमारे लिए स्थिति को संभालेगा। हालांकि यह सबसे सुरुचिपूर्ण समाधान नहीं है, यह काम करता है और देखता है कि कैसे कुछ कंपाइलर्स कुछ स्थानों में आसानी से टूटा हुआ है, और अधिक सुरुचिपूर्ण समाधान कंपेलरों को तोड़ने के लिए होते हैं। (मैं चाहता हूं कि सभी कंपाइलर्स माइक्रोसॉफ्ट के "#pragma एक बार" कमांड को लागू करें, # ifdef के सब कुछ लपेटने से कहीं ज्यादा आसान)

उत्तर

8

इस जटिलता का एक बड़ा सौदा आम तौर पर तीसरे पक्ष के पुस्तकालयों द्वारा हल किया जाता है (सबसे ज्यादा बढ़ावा देना प्रसिद्ध) आप का उपयोग कर रहे हैं। एक शायद ही कभी स्क्रैच से सब कुछ लिखता है ...

+0

बहु-मंच पुस्तकालयों का उपयोग करके मैं आपसे सहमत हूं इस समस्या से निपटने का एक बहुत अच्छा तरीका – thrantir

4

मैं आमतौर पर एक वर्ग में सिस्टम-विशिष्ट कॉल को समाहित करता हूं। यदि आप अपने आवेदन को नए प्लेटफ़ॉर्म पर पोर्ट करने का निर्णय लेते हैं, तो आपको केवल एक फ़ाइल पोर्ट करना होगा ...

0

विभिन्न कार्यों या कक्षाओं का उपयोग करके उन्मूलन जैसी चीज़ों के लिए थोड़ा अधिक ओवरहेड है। जैसे पूर्व प्रोसेसर का उपयोग का प्रयास करें:

#ifdef INTEL_LINUX: 
    code here 
#endif 

#ifdef SOLARIS_POWERPC 
    code here 
#endif 
+0

बहुत सारे सोलारिस पावरपीसी कोडिंग करते हैं? :) – postfuturist

+0

-1: सुविधाओं के लिए परीक्षण, विशिष्ट प्लेटफ़ॉर्म नहीं – dwc

+0

@ steveth45: नहीं, मैंने अभी एक उदाहरण उद्धृत किया है और x86 – Xolve

2

आमतौर पर, पोर्टेबिलिटी इस तरह की समस्या का निर्माण प्रणाली (मेरे मामले में autotools या cmake) जो प्रणाली के विशिष्ट पता लगाने के लिए छोड़ दिया जाता है। अंत में, मुझे इस बिल्ड सिस्टम से config.h मिलता है और फिर मुझे इस हेडर में निरंतर परिभाषित करना होगा (IF परिभाषित करके)।

/* Define to 1 if you have the <math.h> header file. */ 
#define HAVE_MATH_H 

/* Define to 1 if you have the <sys/time.h> header file. */ 
#define HAVE_SYS_TIME_H 

/* Define to 1 if you have the <errno.h> header file. */ 
#define HAVE_ERRNO_H 

/* Define to 1 if you have the <time.h> header file. */ 
#define HAVE_TIME_H 

तो कोड इस तरह (time.h के लिए उदाहरण के लिए) दिखेगा::

#ifdef (HAVE_TIME_H) 
//you can use some function from time.h 
#else 
//find another solution :) 
#endif 
3

मैं सामान्य रूप से बहु मंच पुस्तकालयों का उपयोग

उदाहरण यहां के लिए एक config.h है , बूस्ट या क्यूटी की तरह, वे प्लेटफार्म विशिष्ट कोड से निपटने में मेरी 9 5% समस्याओं का समाधान करते हैं (मैं केवल एकमात्र मंच स्वीकार करता हूं जिसमें जीत-एक्सपी और लिनक्स हैं)। शेष 5% के लिए, मैं आम तौर पर एक या अधिक कक्षाओं में प्लेटफ़ॉर्म विशिष्ट कोड को समाहित करता हूं, # ifdef/# endif अनुभाग

1

डेटा स्वरूपों के लिए - सब कुछ के लिए सादे पाठ का उपयोग करें। कंपाइलर मतभेदों के लिए, सी ++ मानक से अवगत रहें और जी ++ -pedantic जैसे कंपाइलर स्विच का उपयोग करें, जो आपको पोर्टेबिलिटी समस्याओं की चेतावनी देगा।

1

यह आपके द्वारा की जा रही चीज़ों पर निर्भर करता है। एक चीज जो लगभग हमेशा सही विकल्प है, मूल सामग्री को किसी भी लक्षित प्लेटफॉर्म पर पोर्ट करना है, और फिर इसे एक सामान्य एपीआई के साथ सौदा करना है।

उदाहरण के लिए, मैं बहुत संख्यात्मक गणना कोडिंग करता हूं, और कुछ प्लेटफार्मों में बहुत टूटा/गैर मानक कोड होता है: इसे हल करने का तरीका उन कार्यों को पुन: कार्यान्वित करना है, और फिर अपने कोड में हर जगह उन नए कार्यों का उपयोग करना है (प्लेटफार्मों के लिए जो काम करते हैं, नया फ़ंक्शन केवल पुराने को कॉल करता है)।

लेकिन यह केवल निम्न स्तर की सामग्री के लिए वास्तव में काम करता है। जीयूआई के लिए, उच्च स्तर के आईओ, पहले से ही मौजूदा पुस्तकालय का उपयोग करना लगभग हर बार एक बेहतर विकल्प है।

6

फाइलों से लोड किए गए डेटा में एंडियन मुद्दों के लिए, फ़ाइल शीर्षलेख में 0x12345678 जैसे मान एम्बेड करें।

ऑब्जेक्ट जो डेटा लोड करता है, इस मान को देखें, और यदि यह मान के आंतरिक प्रतिनिधित्व से मेल खाता है, तो फ़ाइल में देशी एंडियन मान होते हैं। लोड वहां से सरल है।

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

3

मुझे लगता है कि अन्य उत्तरों ने अंतहीनता को छोड़कर अपनी सभी चिंताओं को दूर करने का एक अच्छा काम किया है, इसलिए मैं इसके बारे में कुछ जोड़ूंगा ... यह केवल बाहरी दुनिया में आपके इंटरफेस में एक समस्या होनी चाहिए। आपकी सभी आंतरिक डेटा प्रोसेसिंग मूल अंत्येष्टि में किया जाना चाहिए। जब टीसीपी/आईपी (या किसी अन्य सॉकेट प्रोटोकॉल) के माध्यम से संचार करते हैं, तो ऐसे फ़ंक्शंस होते हैं जिन्हें आपको हमेशा अपने मानों को नेटवर्क बाइट ऑर्डर से बदलने के लिए उपयोग करना चाहिए। आईआईआरसी, फ़ंक्शंस htons() और htonl(), (नेटवर्क को छोटा होस्ट, लंबे समय तक होस्ट करने के लिए मेजबान) और उनके इनवर्सेस, जिन्हें मैं याद नहीं कर सकता ... शायद ntohl() आदि जैसे कुछ?

एकमात्र अन्य स्थान जो आपको गलत बाइट ऑर्डर वाले डेटा के साथ बातचीत कर रहा है, वह आपके स्थानीय हार्ड ड्राइव से फ़ाइलें पढ़ रहा है, इसलिए अपने फ़ाइल लोडर और लेखकों को समान कार्यों का उपयोग करें (शायद आप नेटवर्क का उपयोग करने से भी दूर हो सकते हैं फ़ंक्शन)।

इन लाइब्रेरी-प्रदान किए गए कार्यों का उपयोग हमेशा उन्मूलन से निपटने के लिए करते हुए (उन कोडों में भी उपयोग करें जिन्हें आप बंदरगाह का इरादा नहीं रखते हैं, जब तक कि आपके पास कोई अनिवार्य कारण न हो - जब आप बंदरगाह का निर्णय लेते हैं तो यह आसान हो जाएगा), आप किसी भी मंच पर कोड चला सकते हैं और देशी अंतहीनता के बावजूद यह "बस काम करेगा"।

1

मूल फ़्लोटिंग पॉइंट समर्थन के बिना प्लेटफॉर्म के लिए, हमने कुछ निश्चित बिंदु प्रकार और कुछ टाइपपीफ का उपयोग किया है। इस तरह:

// native floating points 
typedef float Real; 

या कुछ और की तरह नियत बिन्दु के लिए:

typedef FixedPoint_16_16 Real; 

फिर गणित कार्यों यह लग सकता है:

Real OurMath::ourSin(const Real& value); 

वास्तविक क्रियान्वयन बिल्कुल हो सकता है:

float OurMath::ourSin(const float& value) 
{ 
    return sin(value); 
} 
// for fixed points something more or less trickery stuff 
संबंधित मुद्दे

 संबंधित मुद्दे