การพัฒนาปลั๊กอิน - นักพัฒนา X-Plane (2024)

ปลั๊กอินคือโค้ดปฏิบัติการที่ทำงานภายใน X-Plane ซึ่งขยายสิ่งที่ X-Plane ทำ ปลั๊กอินเป็นแบบแยกส่วน ช่วยให้นักพัฒนาสามารถขยายตัวจำลองได้โดยไม่ต้องมีซอร์สโค้ดในตัวจำลอง บทความนี้จะอธิบายพื้นฐานของปลั๊กอิน วิธีการทำงาน และอธิบายวิธีการเขียนปลั๊กอิน

หากคุณเป็นโปรแกรมเมอร์ที่มีประสบการณ์ คุณอาจคุ้นเคยกับเนื้อหาบางส่วนที่นำเสนอที่นี่แล้ว หากคุณยังไม่ได้ทำการเขียนโปรแกรมแบบโมดูลาร์โดยใช้ DLL เราจะแนะนำแนวคิดนี้และยังมีตัวอย่างการเขียนปลั๊กอินขั้นพื้นฐานทีละขั้นตอนอีกด้วย

ปลั๊กอินคืออะไรและปลั๊กอินทำอะไรได้บ้าง

ก่อนที่จะพูดคุยถึงวิธีการเขียน Plugin เราจะอธิบายคร่าวๆ ว่ามันทำอะไรได้บ้าง คุณอาจไม่จำเป็นต้องใช้ปลั๊กอินสำหรับสิ่งที่คุณพยายามทำให้สำเร็จ และปลั๊กอินอาจไม่สามารถบรรลุสิ่งที่คุณพยายามจะทำได้สำเร็จ

ปลั๊กอินเป็นโค้ดปฏิบัติการที่ทำงานภายใน X-Plane ปลั๊กอินช่วยให้คุณสามารถขยายขีดความสามารถของเครื่องจำลองการบินหรือเข้าถึงข้อมูลของเครื่องจำลองได้ ปลั๊กอินแตกต่างจากโปรแกรมทั่วไปตรงที่ตัวโปรแกรมยังไม่สมบูรณ์ แต่เป็นส่วนของโปรแกรมที่จะถูกเพิ่มลงใน X-Plane ขณะที่มันทำงาน เนื่องจากปลั๊กอินทำงาน "ภายใน" ตัวจำลอง จึงสามารถบรรลุสิ่งที่โปรแกรมสแตนด์อโลนอาจไม่สามารถทำได้ แต่เนื่องจากปลั๊กอินไม่ใช่โปรแกรมเต็มรูปแบบ จึงมีข้อจำกัดที่โปรแกรมทั่วไปไม่มี

ปลั๊กอินสามารถ:

  • เรียกใช้โค้ดจากภายในเครื่องจำลองอย่างต่อเนื่อง (เช่น หนึ่งครั้งต่อรอบการบิน) หรือเพื่อตอบสนองต่อเหตุการณ์ภายในเครื่องจำลอง ตัวอย่างเช่น ปลั๊กอินสามารถทำงานได้อย่างต่อเนื่องภายในเครื่องจำลองและบันทึกข้อมูลลงในไฟล์
  • อ่านข้อมูลจากเครื่องจำลอง ตัวอย่างเช่น ปลั๊กอินสามารถอ่านค่าของเครื่องมือการบินอย่างต่อเนื่องและส่งผ่านเครือข่าย
  • แก้ไขข้อมูลในเครื่องจำลอง เปลี่ยนแปลงการกระทำหรือพฤติกรรม ตัวอย่างเช่น ปลั๊กอินสามารถเปลี่ยนตำแหน่งของเครื่องบิน หรือแทนที่โมเดลการบินของเครื่องจำลองทั้งหมดได้
  • สร้างส่วนติดต่อผู้ใช้ภายในซิม ตัวอย่างเช่น ปลั๊กอินสามารถสร้างหน้าต่างป๊อปอัปพร้อมเครื่องมือหรือกล่องโต้ตอบได้
  • ควบคุมระบบย่อยต่างๆ ของเครื่องจำลอง (API เหล่านี้มีรายละเอียดเพิ่มเติมด้านล่าง)

บางส่วนของเครื่องจำลองถูกควบคุมโดยการเขียนข้อมูลลงในเครื่องจำลอง ตัวอย่างเช่น ในการตั้งค่าความสูงของฐานคลาวด์ เราเพียงแค่ตั้งค่าตัวแปรนั้นในซิม ระบบย่อยอื่นๆ ต้องการการโต้ตอบที่ซับซ้อนมากขึ้นและมี API เฉพาะ ตัวอย่างเช่น มี API สำหรับตั้งโปรแกรมระบบการจัดการการบินของเครื่องจำลอง

ปลั๊กอินและ DLL

ปลั๊กอินคือ DLL จำเป็นต้องมีความเข้าใจเกี่ยวกับ DLL เพื่อทำความเข้าใจวิธีการทำงานของปลั๊กอิน

เกี่ยวกับ DLL

ไลบรารีที่เชื่อมโยงแบบไดนามิก(DLL) คือชุดของฟังก์ชันหรือขั้นตอนที่คอมไพล์แล้วและตัวแปรที่เกี่ยวข้อง DLL แตกต่างจากโปรแกรมทั่วไปในประเด็นสำคัญบางประการ DLL ไม่มีฟังก์ชัน "main" ที่ทำงานเพียงครั้งเดียวเพื่อเรียกใช้โปรแกรมทั้งหมด DLL มีฟังก์ชันมากมายและมีโปรแกรมอื่นอยู่แทนการใช้งานDLL โดยการเรียกใช้ฟังก์ชันเหล่านี้

DLL มีไดเร็กทอรีของฟังก์ชันที่อยู่ภายใน แอปพลิเคชันอื่นๆ สามารถอ่านไดเร็กทอรีนั้นเพื่อค้นหาฟังก์ชันที่ต้องการได้ ฟังก์ชันต่างๆ ในไดเร็กทอรีนี้เรียกว่าส่งออกเนื่องจากมีการกล่าวถึง DLL เพื่อ "ส่งออก" ไปยังโปรแกรมอื่น ไม่ใช่ฟังก์ชันทั้งหมดใน DLL ที่จะถูกส่งออก ฟังก์ชันที่ไม่ได้ส่งออกจะกล่าวว่าเป็นภายใน- โปรแกรมสามารถเรียกใช้ฟังก์ชันที่ส่งออกใน DLL ได้โดยตรงเท่านั้น เนื่องจากจะต้องค้นหาฟังก์ชันเหล่านี้ผ่านไดเร็กทอรี แต่ฟังก์ชันที่ส่งออกใน DLL จะสามารถเรียกใช้ฟังก์ชันภายในได้

DLL มีประสิทธิภาพมากเนื่องจากโปรแกรมที่ใช้ DLL จะค้นหาและรันโค้ดใน DLL เมื่อถูกดำเนินการ ไม่ใช่เมื่อมีการคอมไพล์ พิจารณากรณีของชุดฟังก์ชันทางคณิตศาสตร์สำหรับเครื่องคิดเลข ถ้าเราเพียงรวบรวมฟังก์ชันทางคณิตศาสตร์ลงในโปรแกรมของเรา เมื่อเราเปลี่ยนโปรแกรมทางคณิตศาสตร์ (เช่น เพื่อให้เร็วขึ้นหรือแม่นยำยิ่งขึ้น) เราจะต้องคอมไพล์โปรแกรมทั้งหมดของเราใหม่ หากเรารู้ว่าฟังก์ชันทางคณิตศาสตร์มีแนวโน้มที่จะเปลี่ยนแปลง เราสามารถใส่ลงใน DLL และให้โปรแกรมเครื่องคิดเลขค้นหาฟังก์ชันเหล่านี้เมื่อทำงาน เนื่องจากเครื่องคิดเลขค้นหาฟังก์ชันทางคณิตศาสตร์ทุกครั้งที่ทำงาน เราจึงสามารถสร้าง DLL ใหม่ที่มีชื่อฟังก์ชันเดียวกัน แต่มีการใช้งานที่ดีกว่า และแทนที่ด้วย DLL เก่า ฟังก์ชันเครื่องคิดเลขจะไม่สนใจตราบใดที่ฟังก์ชันมีชื่อเหมือนกันและรับอินพุตเหมือนกัน สิ่งนี้ช่วยให้เราสามารถอัพเกรดหรือเปลี่ยนแปลงพฤติกรรมของโปรแกรมเครื่องคิดเลขของเราโดยไม่ต้องคอมไพล์ใหม่

ตัวอย่างข้างต้นค่อนข้างซับซ้อน แต่จะเกิดอะไรขึ้นหากบริษัทหนึ่งสร้างโปรแกรมเครื่องคิดเลขและอีกบริษัทหนึ่งสร้างฟังก์ชันทางคณิตศาสตร์? บริษัทที่สร้างฟังก์ชันทางคณิตศาสตร์อาจไม่มีโค้ดสำหรับเครื่องคิดเลขและอาจไม่สามารถคอมไพล์ใหม่ได้ ดังนั้นการสร้างแอปพลิเคชันขนาดใหญ่เพียงแอปเดียวจึงไม่เป็นที่ยอมรับ นอกจากนี้ บริษัทที่สร้างฟังก์ชันทางคณิตศาสตร์อาจไม่ต้องการให้บริษัทที่สร้างเครื่องคิดเลขมีซอร์สโค้ดของตน DLLs แก้ไขปัญหาทั้งสองนี้ บริษัทที่สร้างฟังก์ชันทางคณิตศาสตร์สามารถจัดเตรียมฟังก์ชันทางคณิตศาสตร์ใหม่ให้กับบริษัทเครื่องคิดเลขโดยไม่จำเป็นต้องคอมไพล์เครื่องคิดเลขใหม่ บริษัทที่ผลิตเครื่องคิดเลขสามารถใช้ฟังก์ชันทางคณิตศาสตร์ได้โดยไม่ต้องเข้าถึงโค้ดของตน

โปรแกรมใช้ DLL โดยการเชื่อมโยงถึงมัน สิ่งนี้จะเกิดขึ้นเมื่อมีการรันโปรแกรม เมื่อโปรแกรมลิงก์ไปยัง DLL โปรแกรมจะตรวจสอบไดเร็กทอรี DLL และค้นหาฟังก์ชันที่ส่งออกทั้งหมดที่ต้องการ การเชื่อมโยงมีสองประเภท:ฮาร์ดลิงก์(หรือเรียกอีกอย่างว่าการเชื่อมโยงอย่างแน่นหนา) และอ่อนแอ-การเชื่อมโยง(หรือเรียกอีกอย่างว่าการเชื่อมโยงแบบอ่อน) เมื่อโปรแกรมฮาร์ดลิงก์กับ DLL โปรแกรมจะต้องค้นหาทุกฟังก์ชันที่ต้องการในไดเร็กทอรี DLLs เพื่อรัน หาก DLL ขาดฟังก์ชัน โปรแกรมจะไม่ทำงาน เมื่อโปรแกรมเชื่อมโยงอย่างอ่อนแอกับ DLL โปรแกรมสามารถทำงานได้แม้ว่าจะไม่พบฟังก์ชันทั้งหมดที่ต้องการก็ตาม

DLL ยังสามารถลิงก์ไปยัง DLL อื่นๆ ได้ ด้วยวิธีนี้จึงสามารถสร้างลูกโซ่ของ DLL ได้ ตัวอย่างเช่น บริษัทที่สร้างฟังก์ชันทางคณิตศาสตร์อาจใช้ DLL อื่นของบริษัทอื่นที่เพิ่งทำการคำนวณขั้นพื้นฐานบางอย่าง

DLL ไม่ใช่โปรแกรมเต็มรูปแบบ พวกมันไม่ทำงานพร้อมกับโปรแกรม และไม่มีหน่วยความจำของตัวเอง เป็นเพียงไลบรารีของโค้ด รหัสนั้นอาจแบ่งปันข้อมูลกับโปรแกรมโฮสต์หากต้องการ ตัวอย่างเช่น โปรแกรมเครื่องคิดเลขอาจส่งที่อยู่ของบัฟเฟอร์ภายในไปยังไลบรารีคณิตศาสตร์ จากนั้นโปรแกรมคณิตศาสตร์อาจเติมตัวเลขลงในบัฟเฟอร์

หาก DLL หรือโปรแกรมหลายตัวเชื่อมโยงไปยัง DLL ตัวเดียว DLL ตัวนั้นที่ถูกเชื่อมโยงจะถูกโหลดเพียงครั้งเดียว และอาจมีตัวแปรส่วนกลางเพียงชุดเดียวเท่านั้น สิ่งนี้ทำให้ DLL สามารถสื่อสารระหว่างกันได้ ตัวอย่างเช่น DLL หลายตัวที่โปรแกรมเครื่องคิดเลขใช้อาจใช้ DLL คำนวณวันที่ตัวเดียว ซึ่งสามารถระบุสิ่งต่างๆ เช่น วันในสัปดาห์เมื่อสามปีที่แล้ว หาก DLL ที่คำนวณวันที่นั้นมีตัวแปรภายในสำหรับวันปัจจุบันของสัปดาห์ DLL ทั้งหมดที่เชื่อมโยงกับตัวแปรดังกล่าวจะเห็น หาก DLL ตัวหนึ่งเปลี่ยนตัวแปรนั้น ตัวแปรจะถูกเปลี่ยนสำหรับ DLL ทั้งหมด ด้วยวิธีนี้ DLL สามารถสื่อสารระหว่างกันโดยการแบ่งปันข้อมูลเดียวกัน

ปลั๊กอินและตัวจัดการปลั๊กอินคือ DLL

ระบบปลั๊กอิน X-Plane ใช้ DLLs องค์ประกอบหลักของระบบนี้คือตัวจัดการปลั๊กอิน X-Plane(หรือ XPLM) XPLM เป็นไลบรารีของโค้ด (คอมไพล์เป็น DLL!) ที่จัดการปลั๊กอิน X-Plane ลิงก์ไปยัง XPLM และปลั๊กอินทั้งหมดลิงก์ไปยัง XPLM จากนั้น XPLM จะทำหน้าที่เป็นฮับกลางในระบบปลั๊กอิน

ปลั๊กอินประกอบด้วยโค้ดที่จะทำงานภายในเครื่องจำลอง โดยส่งออกฟังก์ชันที่ XPLM สามารถเรียกใช้ได้ และ XPLM จะค้นหาไดเร็กทอรีของปลั๊กอิน DLL เพื่อค้นหา

ในทำนองเดียวกัน XPLM มีฟังก์ชันที่เสียบเข้าไปจำเป็นต้องเปลี่ยนซิม อ่านข้อมูล สร้างอินเทอร์เฟซผู้ใช้ ฯลฯ XPLM ส่งออกฟังก์ชันเหล่านี้ไปยังไดเร็กทอรี DLL เพื่อให้ปลั๊กอินสามารถค้นหาและเรียกใช้ฟังก์ชันเหล่านี้ได้

ปลั๊กอินไม่เคยสื่อสารโดยตรงกับ X-Plane พวกเขาจะต้องผ่าน XPLM เสมอ เพื่อวัตถุประสงค์ในทางปฏิบัติ XPLMเป็นตัวจำลองไปยังปลั๊กอิน ปลั๊กอินไม่เคยพูดคุยกับปลั๊กอินอื่นโดยตรง แต่จะส่งข้อความผ่าน XPLM แทน การสื่อสารกับปลั๊กอินอื่นๆ มีอยู่ในบทความ “การทำงานกับปลั๊กอินอื่นๆ” รายละเอียดวิธีที่ XPLM โต้ตอบกับเครื่องจำลองครอบคลุมอยู่ในภาคผนวก “สถาปัตยกรรม XPLM” เราไม่จำเป็นต้องรู้ว่า XPLM และ X-Plane โต้ตอบกันอย่างไรในการเขียนปลั๊กอิน

แนวคิดปลั๊กอิน

ส่วนต่างๆ ของระบบปลั๊กอิน

ระบบปลั๊กอินมีสี่ส่วนหลัก:

  1. เอ็กซ์-เพลน- X-Plane เป็นแอปพลิเคชันโฮสต์ ปลั๊กอินทั้งหมดทำงานภายในพื้นที่หน่วยความจำของ X-Plane
  2. ตัวจัดการปลั๊กอิน X-Plane(เอ็กซ์พีแอลเอ็ม). XPLM คือ DLL ที่ทำหน้าที่เป็นศูนย์กลางสำหรับกิจกรรมปลั๊กอินทั้งหมด XPLM สื่อสารกับ X-Plane
  3. ปลั๊กอิน- ปลั๊กอินคือ DLL ที่สื่อสารกับ XPLM ปลั๊กอินไม่ได้พูดคุยกับเครื่องจำลองโดยตรง ปลั๊กอินปรับเปลี่ยนพฤติกรรมของตัวจำลองโดยการเรียกใช้ฟังก์ชันภายในไลบรารี XPLM เพื่อให้ตัวจำลองทำสิ่งต่าง ๆ หรือเปลี่ยนข้อมูลของตัวจำลอง
  4. ห้องสมุดอื่นๆ- ปลั๊กอินยังสามารถใช้ไลบรารีหรือ DLL อื่นที่มีฟังก์ชันที่มีประโยชน์ได้

ลายเซ็นปลั๊กอิน

ปลั๊กอินแต่ละตัวมีลายเซ็น ปลั๊กอินจะบอกลายเซ็น XPLM เมื่อมีการเตรียมใช้งานครั้งแรก ลายเซ็นนี้จะระบุปลั๊กอินโดยไม่ซ้ำกันและแตกต่างจากปลั๊กอินอื่นๆ ทั้งหมด ลายเซ็นถูกสร้างขึ้นจากการรวมคำสำคัญจากซ้ายไปขวา โดยเริ่มจากองค์กรที่รับผิดชอบในการสร้างปลั๊กอิน ตัวอย่างเช่น หาก XYZResearch สร้างปลั๊กอินเพื่อวัดประสิทธิภาพของเครื่องยนต์โดยเป็นส่วนหนึ่งของแพ็คเกจการวินิจฉัยเที่ยวบิน ก็อาจใช้ลายเซ็นเช่น:

XYZResearch.diagnostics.engine_Performance_meter

คุณสามารถใช้สตริงใดก็ได้ที่คุณต้องการสำหรับลายเซ็นของปลั๊กอิน แต่คุณควรเลือกสตริงแรกตามองค์กร (ไม่ว่าจะเป็นเชิงพาณิชย์หรือสำหรับแชร์แวร์) เพื่อที่คุณจะได้ไม่เลือกชื่อเดียวกันกับปลั๊กอินอื่นโดยไม่ได้ตั้งใจ (หาก XPLM พบปลั๊กอินหลายตัวที่ติดตั้งด้วยลายเซ็นเดียวกัน ระบบจะโหลดเพียงอันเดียวเท่านั้น)

การเปิดใช้งานปลั๊กอิน

ปลั๊กอินอาจเปิดหรือปิดใช้งานได้ ปลั๊กอินที่เปิดใช้งานจะมีการเรียกกลับ (หากมีสิ่งใดที่ต้องถูกเรียก) แต่การเรียกกลับที่ปิดใช้งานจะไม่เป็นเช่นนั้น ปลั๊กอินที่ปิดใช้งานไม่สามารถส่งผลกระทบต่อซิมได้เนื่องจากไม่มีการเรียกการเรียกกลับ การปิดใช้งานจะทำให้ผู้ใช้สามารถปิดปลั๊กอินที่พวกเขาไม่ต้องการใช้หรือกำลังมีปัญหาได้ กล่องโต้ตอบในโปรแกรมจำลองทำให้ผู้ใช้สามารถเปิดและปิดใช้งานปลั๊กอินได้

ปลั๊กอินทั้งหมดเริ่มปิดการใช้งานเมื่อมีการโหลด จากนั้นแต่ละอันจะเปิดใช้งานทีละอันเมื่อซิมพร้อมที่จะเริ่มต้น ปลั๊กอินถูกปิดใช้งานก่อนที่จะยกเลิกการโหลดเมื่อผู้ใช้ออกจากโปรแกรมจำลอง หากก่อนหน้านี้ผู้ใช้ปิดใช้งานปลั๊กอินก่อนที่จะออกจากตัวจำลองหรือปิดใช้งานปลั๊กอินทั้งหมดเมื่อเริ่มต้น (โดยกดปุ่ม Shift ค้างไว้ในขณะที่ตัวจำลองเริ่มทำงาน) ปลั๊กอินจะเริ่มปิดใช้งานและคงปิดใช้งานอยู่จนกว่าผู้ใช้จะเปิดใช้งาน

ปลั๊กอินจะได้รับการติดต่อกลับเมื่อมีการเปิดใช้งานและปิดใช้งาน แต่ไม่จำเป็นต้องดำเนินการใดๆ เพื่อตอบสนองต่อการโทรกลับนี้ Windows จะถูกซ่อนโดยอัตโนมัติ รายการเมนูจะถูกปิดใช้งาน และตัวจับเวลาจะหยุดชั่วคราวเมื่อปลั๊กอินถูกปิดใช้งาน ปลั๊กอินที่จัดสรรทรัพยากรอื่นอาจต้องการเพิ่มพื้นที่ว่างเมื่อปิดใช้งาน ตัวอย่างเช่น หากปลั๊กอินสื่อสารกับเซิร์ฟเวอร์ผ่านอินเทอร์เน็ต ปลั๊กอินอาจต้องการตัดการเชื่อมต่อจากเซิร์ฟเวอร์เมื่อปิดใช้งานและเชื่อมต่อใหม่เมื่อเปิดใช้งาน

กายวิภาคของปลั๊กอิน

ส่วนนี้จะอธิบายวิธีการตั้งค่าปลั๊กอินโดยละเอียด

ปลั๊กอินคือ DLL ที่มีฟังก์ชันมากมาย ในบรรดาสิ่งเหล่านี้คือการเรียกกลับต่างๆ ที่ XPLM เรียกใช้เพื่อแจ้งปลั๊กอินของเหตุการณ์ รวมถึงฟังก์ชันตัวช่วย ยูทิลิตี้ ฯลฯ ที่ปลั๊กอินต้องการ

การโทรกลับในปลั๊กอินมีสองรสชาติ:

  1. ที่จำเป็นการเรียกกลับเป็นฟังก์ชันที่ปลั๊กอินส่งออกเป็น DLL XPLM ค้นหาฟังก์ชันเหล่านี้และเรียกใช้ฟังก์ชันเหล่านี้เมื่อเหมาะสม ปลั๊กอินจะต้องส่งออกการโทรกลับที่จำเป็นทั้งห้าครั้งด้านล่าง ไม่เช่นนั้นมันจะโหลดไม่ถูกต้อง คุณไม่จำเป็นต้องทำอะไรก็ตามในการโทรกลับ; อาจเป็นฟังก์ชันว่างก็ได้ XPLM ค้นหาการเรียกกลับที่ต้องการโดยการค้นหาไดเร็กทอรี DLLs
  2. ลงทะเบียนแล้วการโทรกลับเป็นฟังก์ชันที่คุณส่งกลับไปยัง XPLM เพื่อเข้าถึงฟังก์ชันการทำงานของตัวจำลองเพิ่มเติม ตัวอย่างเช่น หากคุณสร้างหน้าต่าง คุณจะจัดเตรียมฟังก์ชันการเรียกกลับซึ่งจะถูกเรียกเมื่อผู้ใช้คลิกในหน้าต่าง ฟังก์ชันที่ลงทะเบียนแล้วไม่จำเป็นต้องส่งออกจาก DLL แต่คุณส่งตัวชี้ไปยังฟังก์ชันโดยตรงไปยัง XPLM แทน

คุณสามารถลงทะเบียนการโทรกลับจากการโทรกลับที่ต้องการหรือจากการโทรกลับอื่นๆ ตัวอย่างเช่น คุณสามารถลงทะเบียนการโทรกลับที่จะถูกเรียกภายใน 5 นาทีเมื่อปลั๊กอินเริ่มต้นใช้งาน จากนั้นอีกห้านาทีต่อมาที่โทรกลับ คุณสามารถสร้างหน้าต่างและลงทะเบียนการโทรกลับเมื่อคลิกหน้าต่างได้

การเขียนโปรแกรมปลั๊กอินแตกต่างจากการเขียนโปรแกรมแอปพลิเคชันทั่วไป ในแอปพลิเคชันทั่วไป เราจะเขียนโปรแกรมหลักที่รันครั้งเดียวตั้งแต่ต้นจนจบ ในปลั๊กอิน มีการเรียกใช้ฟังก์ชันเล็กๆ จำนวนมากในเวลาที่ต่างกัน ด้วยวิธีนี้ การเขียนโปรแกรมปลั๊กอินจะคล้ายกับการเขียนโปรแกรม UI ที่ขับเคลื่อนด้วยเหตุการณ์

การโทรกลับที่จำเป็น

มีการเรียกกลับที่จำเป็นห้ารายการที่ปลั๊กอินต้องใช้ ซึ่งทั้งหมดถูกเรียกโดย XPLM:

  • XPluginStart()- สิ่งนี้เรียกว่าเมื่อมีการโหลดปลั๊กอินครั้งแรก คุณสามารถใช้มันเพื่อจัดสรรทรัพยากรถาวรและลงทะเบียนการโทรกลับอื่น ๆ ที่คุณต้องการ นี่เป็นเวลาที่ดีในการตั้งค่าอินเทอร์เฟซผู้ใช้ การโทรกลับนี้ยังส่งคืนชื่อปลั๊กอิน ลายเซ็น และคำอธิบายไปยัง XPLM
  • XPluginเปิดใช้งาน()- สิ่งนี้เรียกว่าเมื่อเปิดใช้งานปลั๊กอิน คุณไม่จำเป็นต้องดำเนินการใดๆ ในการติดต่อกลับนี้ แต่ถ้าคุณต้องการ เราสามารถจัดสรรทรัพยากรที่เราต้องการเฉพาะในขณะที่เปิดใช้งานเท่านั้น
  • XPluginปิดการใช้งาน()- สิ่งนี้จะถูกเรียกเมื่อปลั๊กอินถูกปิดใช้งาน คุณไม่จำเป็นต้องดำเนินการใดๆ ในการติดต่อกลับนี้ แต่หากเราต้องการ คุณสามารถจัดสรรทรัพยากรที่จำเป็นเฉพาะในขณะที่เปิดใช้งานเท่านั้น เมื่อปิดใช้งานแล้ว ปลั๊กอินอาจไม่ทำงานอีกเป็นเวลานาน ดังนั้นคุณควรปิดการเชื่อมต่อเครือข่ายที่อาจหมดเวลา
  • XPluginStop()- สิ่งนี้ถูกเรียกก่อนที่จะยกเลิกการโหลดปลั๊กอิน คุณควรยกเลิกการลงทะเบียนการโทรกลับทั้งหมด ปล่อยทรัพยากรทั้งหมด ปิดไฟล์ทั้งหมด และล้างข้อมูลโดยทั่วไป
  • XPluginรับข้อความ()- สิ่งนี้จะถูกเรียกเมื่อปลั๊กอินหรือ X-Plane ส่งข้อความถึงปลั๊กอิน ดูบทความเรื่อง “การสื่อสารและการส่งข้อความระหว่างปลั๊กอิน” สำหรับข้อมูลเพิ่มเติม XPLM จะแจ้งให้คุณทราบเมื่อมีเหตุการณ์เกิดขึ้นในเครื่องจำลอง (เช่น ผู้ใช้เครื่องบินตกหรือเลือกเครื่องบินรุ่นใหม่) โดยการเรียกใช้ฟังก์ชันนี้

การลงทะเบียนการโทรกลับเพิ่มเติม

SDK API หลายส่วนกำหนดให้คุณต้องลงทะเบียนการเรียกกลับเพิ่มเติม ตัวอย่างบางส่วน:

  • เมื่อต้องการสร้างรายการเมนู คุณต้องลงทะเบียนการติดต่อกลับซึ่งจะถูกเรียกเมื่อผู้ใช้คลิกที่รายการเมนู การโทรกลับนี้สามารถดำเนินการตามที่รายการเมนูบอกได้ (ดูที่XPLMเมนูส่วนหัวสำหรับข้อมูลเพิ่มเติม)
  • เมื่อต้องการสร้างหน้าต่าง คุณต้องลงทะเบียนการติดต่อกลับซึ่งจะถูกเรียกเมื่อผู้ใช้คลิกในหน้าต่าง คุณจะต้องลงทะเบียนการโทรกลับเพื่อจัดการการวาดหน้าต่าง (ดูXPLMCreateWindowEx() สำหรับข้อมูลเพิ่มเติม)

คุณมักจะต้องการลงทะเบียนการโทรกลับเพิ่มเติมเหล่านี้จากการโทรกลับ XPluginStart() ของคุณและยกเลิกการลงทะเบียนจาก XPluginStop()

เซสชันทั่วไปของโปรแกรมจำลองอาจเป็นดังนี้:

  1. ผู้ใช้เริ่มโปรแกรมจำลอง
  2. ตัวจำลอง (ผ่าน XPLM) โหลดปลั๊กอินและเรียก XPluginStart() ของคุณ
  3. ปลั๊กอินของคุณจะสร้างรายการเมนูและลงทะเบียนการติดต่อกลับ
  4. จากนั้นตัวจำลองจะเรียกใช้ฟังก์ชัน XPluginEnable() เพื่อแจ้งให้คุณทราบว่าขณะนี้ปลั๊กอินเปิดใช้งานแล้ว
  5. ผู้ใช้คลิกที่รายการเมนูของคุณ ดังนั้นเครื่องจำลองจะโทรหาคุณXPLMMenuHandler_fโทรกลับ.
  6. ฟังก์ชันโทรกลับของคุณจะทำอะไรบางอย่าง ตัวอย่างเช่น อาจเขียนข้อมูลบางอย่างลงในไฟล์
  7. ผู้ใช้ออกจากโปรแกรมจำลอง
  8. ตัวจำลองจะเรียกใช้ฟังก์ชัน XPluginDisable() ของคุณ จากนั้นจึงเรียกฟังก์ชัน XPluginStop() ของคุณ
  9. ปลั๊กอิน DLL ของคุณถูกยกเลิกการโหลด และเครื่องจำลองปิดการทำงาน

ปลั๊กอินโต้ตอบกับ X-Plane อย่างไร

ปลั๊กอินโต้ตอบกับตัวจำลองโดยการเรียกใช้ฟังก์ชันใน XPLM DLL ฟังก์ชันเหล่านี้ถูกกำหนดไว้ในไฟล์ส่วนหัวที่ขึ้นต้นด้วย XPLM ตัวอย่างเช่น:

  • หากปลั๊กอินต้องการอ่านหรือเขียนข้อมูลจากหรือไปยังเครื่องจำลอง ปลั๊กอินนั้นจะใช้ API ที่กำหนดไว้XPLMDataAccess-
  • หากปลั๊กอินต้องการสร้างอินเทอร์เฟซผู้ใช้ ปลั๊กอินนั้นจะใช้ API ที่กำหนดไว้XPLMDisplay-
  • หากปลั๊กอินต้องการดำเนินการคำสั่ง (เช่น หยุดซิมชั่วคราว) ปลั๊กอินจะใช้ API ในนั้นXPMLยูทิลิตี้-

ตัวอย่างเช่น สมมติว่าคุณต้องการสร้างปลั๊กอินที่ใช้รายการเมนูหยุดชั่วคราวซิม ปลั๊กอินของคุณก็จะโทรXPLMCommandKeyStroke() โดยมีค่า xplm_key_pause คงที่จากภายในการโทรกลับเมนูของคุณ

ดูส่วน "API ที่พร้อมใช้งาน"ของหน้าแรกของ SDK เพื่อดูรายการ API ที่พร้อมใช้งานทั้งหมด

ข้อจำกัดของปลั๊กอิน

ปลั๊กอินทำงานพร้อมกันภายในกระบวนการ X-Plane สิ่งนี้มีส่วนสำคัญพื้นฐานบางประการ:

  • ปลั๊กอินและโปรแกรมจำลองจะไม่ทำงานพร้อมกัน หากปลั๊กอินช้า อัตราเฟรมของเครื่องจำลองก็จะช้าลงเช่นกัน
  • ปลั๊กอินอยู่ในกระบวนการเดียวกับตัวจำลอง หากปลั๊กอินขัดข้อง จะทำให้ตัวจำลองทั้งหมดเสียหาย ปลั๊กอินสามารถเขียนลวกๆ บนหน่วยความจำจำลองได้
  • คุณไม่สามารถใช้ X-Plane SDK จากกระบวนการอื่นได้

สิ่งเหล่านี้ทั้งหมดอาจแก้ไขได้โดยการเขียนโค้ดเพิ่มเติม (เช่น การสื่อสารระหว่างกระบวนการหรือโค้ดเธรด) แต่สิ่งเหล่านี้ไม่ได้เป็นส่วนหนึ่งของระบบปลั๊กอินพื้นฐาน

การเขียนโปรแกรมสำนวนใน XPLM

สำนวนการเขียนโปรแกรมเป็นรูปแบบหนึ่งของการเขียนโค้ดที่ใช้ในการบรรลุเป้าหมายบางอย่าง API ปลั๊กอินเขียนด้วยภาษา C เพื่อให้เข้าถึงภาษาได้หลากหลายที่สุดเท่าที่จะเป็นไปได้ อย่างไรก็ตาม การออกแบบระบบค่อนข้างเน้นไปที่วัตถุ เพื่อให้บรรลุเป้าหมายนี้ในภาษาที่ไม่เน้นเชิงวัตถุ เราใช้สำนวนต่อไปนี้:

ที่จับทึบแสง

หมายเลขอ้างอิงทึบแสงเป็นค่าที่ใช้ในการระบุอ็อบเจ็กต์ที่สร้างขึ้นภายในระบบปลั๊กอิน จุดจับทึบแสงมักจะถูกกำหนดให้เป็นจำนวนเต็มหรือเป็นโมฆะพอยน์เตอร์ หมายเลขอ้างอิงเป็น 'ทึบแสง' เนื่องจากปลั๊กอินไม่ทราบว่าหมายถึงอะไรหรือโครงสร้างภายในแสดงถึงอะไร คุณไม่ควรพยายามทำอะไรโดยใช้แฮนเดิลทึบแสง ยกเว้นส่งกลับไปยัง SDK API

อายุการใช้งานโดยทั่วไปของวัตถุจะเป็นดังนี้: ก่อนอื่นคุณต้องสร้างวัตถุและรับแฮนเดิลทึบแสง จากนั้นคุณทำการเรียกใช้ฟังก์ชันผ่านที่จับนั้นเพื่อจัดการมัน สุดท้าย คุณเรียกใช้ฟังก์ชันเพื่อปล่อยวัตถุโดยส่งผ่านจุดจับเข้าไปอีกครั้ง จากจุดนั้นที่จับก็ใช้ไม่ได้อีกต่อไป

โทรกลับ

ตามที่กล่าวไว้ข้างต้น การเรียกกลับเป็นฟังก์ชันในโค้ดที่ตัวจำลองเรียกใช้เพื่อให้บรรลุพฤติกรรมเฉพาะ ตัวอย่างเช่น เมื่อเครื่องจำลองจำเป็นต้องวาดหน้าต่าง เครื่องจำลองจะเรียกการเรียกกลับแบบดึงที่คุณระบุเมื่อคุณสร้างหน้าต่าง

โดยทั่วไปจะมีการระบุการเรียกกลับเมื่อมีการสร้างออบเจ็กต์และจัดเตรียมลักษณะการทำงานเฉพาะสำหรับออบเจ็กต์นั้น การให้การติดต่อกลับนั้นคล้ายคลึงกับการเอาชนะฟังก์ชันเสมือน มันช่วยให้คุณปรับแต่งพฤติกรรมของวัตถุได้

ค่าอ้างอิง (“refcons”)

API ทั้งหมดที่ใช้การเรียกกลับยังใช้ “ค่าคงที่อ้างอิง” ด้วย สิ่งเหล่านี้คือพอยน์เตอร์ที่จะถูกส่งกลับไปยังการโทรกลับเมื่อมีการโทรกลับ สิ่งนี้ทำให้คุณสามารถระบุข้อมูลเฉพาะบางประเภทด้วยการใช้การโทรกลับที่แตกต่างกัน การใช้ refcons บางประการ ได้แก่:

  • สำหรับภาษาโปรแกรมเชิงวัตถุ คุณสามารถส่งตัวชี้ไปยังวัตถุที่ควรจะทำงานการเรียกกลับ เมื่อโทรกลับ มันจะรู้ว่าต้องดำเนินการกับวัตถุใด
  • สำหรับการเรียกกลับที่ให้ลักษณะการทำงานกับหลายหน้าต่าง คุณสามารถระบุตัวชี้ไปยังข้อมูลสำหรับหน้าต่างเฉพาะนั้นได้
  • สำหรับการเรียกกลับที่ดำเนินการคำสั่ง คุณสามารถระบุคำสั่งโดยใช้ข้อมูลที่เราเลือกได้

คุณไม่จำเป็นต้องใช้ refcons (คุณสามารถส่งผ่านค่า NULL ได้) มีไว้เพื่อความสะดวกเท่านั้น โดยทั่วไปหากข้อมูลที่ดำเนินการเรียกกลับเป็นแบบสากล คุณไม่จำเป็นต้องมีการตรวจสอบซ้ำ แต่หากมีสำเนาของข้อมูลนั้นหลายชุดต่อออบเจ็กต์ คุณจะต้องทำ

การเขียนปลั๊กอิน

ส่วนนี้อธิบายกระบวนการสร้างปลั๊กอินอย่างง่ายทีละขั้นตอน

การสร้างโครงการปลั๊กอิน

ปลั๊กอิน SDK มาพร้อมกับปลั๊กอินตัวอย่างจำนวนหนึ่งพร้อมกับโปรเจ็กต์ตัวอย่างที่เกี่ยวข้อง คุณสามารถดูโครงการตัวอย่างล่าสุดได้ในส่วน "โค้ดตัวอย่าง"ของหน้าแรกของ SDK

การพัฒนาปลั๊กอินใน C

การพัฒนาปลั๊กอินใน C นั้นตรงไปตรงมา เพียงใช้ฟังก์ชันการโทรกลับที่จำเป็นและเขียนการโทรกลับเพิ่มเติม ข้อควรพิจารณาบางประการ:

  • การเรียกกลับที่จำเป็นจะต้องถูกส่งออกจาก DLL กระบวนการทำเช่นนี้เป็นเฉพาะคอมไพเลอร์และเฉพาะระบบปฏิบัติการ สำหรับ C และ C++ บน Microsoft Visual Studio, Xcode และ GCC เรามี PLUGIN_APImacro เพื่อทำให้ง่ายขึ้น
  • คุณต้องรวมส่วนหัว XPLM เพื่อเรียกใช้ฟังก์ชันและเชื่อมโยงกับ XPLM_64.dll เพื่อสร้าง DLL คุณควรทำฮาร์ดไดนามิกลิงก์กับ XPLM_64.dll คุณทำไม่ต้องใช้เดียวกันXPLM_64.dll เพื่อเชื่อมโยงเมื่อรันในซิม

การพัฒนาปลั๊กอินใน C ++

การพัฒนาปลั๊กอินใน C++ นั้นคล้ายคลึงกับการพัฒนาใน C สิ่งหนึ่งที่ควรทราบเพิ่มเติมคือคุณต้องระวังอย่าทำให้การโทรกลับที่จำเป็นเสียหาย โดยปกติ คอมไพเลอร์ C++ จะเปลี่ยนชื่อฟังก์ชันเป็นคำที่ไม่มีความหมายเพื่อแยกความแตกต่างระหว่างฟังก์ชันที่มีชื่อเดียวกันและอาร์กิวเมนต์ต่างกัน (ซึ่งพูดพล่อยๆ จะแตกต่างกันไปขึ้นอยู่กับอาร์กิวเมนต์ของฟังก์ชัน) หากฟังก์ชันมีชื่อไม่ครบถ้วน X-Plane จะไม่พบฟังก์ชันเหล่านั้นและจะไม่โหลดปลั๊กอิน เพื่อหลีกเลี่ยงปัญหานี้ ให้ใช้ไวยากรณ์ "extern C"- หากคุณใช้มาโคร PLUGIN_API การดำเนินการนี้จะเสร็จสิ้นสำหรับคุณ

การพัฒนาปลั๊กอินในภาษาระดับสูงอื่น

คุณสามารถพัฒนาปลั๊กอินในภาษาระดับสูงอื่นๆ ที่รองรับรูปแบบการโทร C ติดต่อเราเพื่อค้นหาการสนับสนุนสำหรับภาษาที่กำหนด

การพัฒนาปลั๊กอินสำหรับ Mac

ปลั๊กอินบน macOS เป็นไลบรารี Xcode สามารถสร้างไลบรารีเหล่านี้ได้อย่างง่ายดาย และมีตัวอย่างให้มาพร้อมกับ SDK

เมื่อทำงานกับ Mac เราควรเชื่อมโยงกับ CoreFoundation.framework และ XPLM.framework (รวมถึงเฟรมเวิร์กอื่น ๆ ที่คุณต้องการ เช่นXPWidgets.framework และ OpenGL.framework)

การพัฒนาปลั๊กอินสำหรับพีซี

ปลั๊กอินบน Windows คือ DLL Visual Studio สามารถสร้าง DLL ได้อย่างง่ายดาย และมีตัวอย่างให้มาพร้อมกับ SDK

การพัฒนาปลั๊กอินข้ามแพลตฟอร์ม

X-Plane ทำงานบน Mac, Windows และ Linux ฟังก์ชั่นทั้งหมดในระบบปลั๊กอินทำงานข้ามแพลตฟอร์ม คุณอาจเขียนปลั๊กอินที่สามารถคอมไพล์และปรับใช้บนทั้งสองแพลตฟอร์มด้วยซอร์สโค้ดเดียวกัน ต่อไปนี้คือระบบย่อยบางส่วนที่ใช้และผลกระทบ:

  • ปฏิสัมพันธ์ของเครื่องบินเอ็กซ์ XPLM API ทั้งหมดเป็นแบบข้ามแพลตฟอร์ม
  • การเข้าถึงไฟล์ ใช้ไลบรารี C มาตรฐานเพื่อเข้าถึงไฟล์
  • โครงสร้างไดเร็กทอรี XPLM API มีการค้นหาไดเร็กทอรีระบบไฟล์ข้ามแพลตฟอร์มและจัดเตรียมตัวคั่นไดเร็กทอรีแบบเนทิฟแพลตฟอร์ม (ดูXPMLยูทิลิตี้-
  • กราฟิกและ UI กราฟิกและ UI ทั้งหมดทำผ่าน OpenGL และดังนั้นจึงข้ามแพลตฟอร์มได้อย่างสมบูรณ์
  • เครือข่าย. ในขณะนี้ ยังไม่มีเธรด API ข้ามแพลตฟอร์ม ติดต่อเราเพื่อขอวิธีแก้ปัญหาที่เป็นไปได้ซึ่งอยู่ในระหว่างดำเนินการ
  • การทำเกลียว ในขณะนี้ ยังไม่มีเธรด API ข้ามแพลตฟอร์ม

หากคุณกำลังพัฒนาโค้ดสำหรับแพลตฟอร์มหนึ่งที่สามารถคอมไพล์บนอีกแพลตฟอร์มได้ โปรดติดต่อเราเพื่อขอความช่วยเหลือในการสร้างปลั๊กอินข้ามแพลตฟอร์ม

การวิเคราะห์ปลั๊กอินตัวอย่าง

ปลั๊กอินตัวอย่าง Hello Worldมอบโปรเจ็กต์ที่สมบูรณ์สำหรับ Windows, Mac และ Linux—ดาวน์โหลดโปรเจ็กต์ที่เหมาะกับแพลตฟอร์มของคุณได้เลย แล้วเปิดในโปรแกรมแก้ไขข้อความ

ปลั๊กอินตัวอย่างมีการโทรกลับที่จำเป็นทั้งหมด และจะบันทึกการโทรกลับอื่นๆ จำนวนหนึ่ง ลองดูรายละเอียดเพิ่มเติมอีกเล็กน้อย

  • XPluginStart()
    • สำเร็จสองสิ่ง:
      • ให้ข้อมูลเกี่ยวกับปลั๊กอิน (ผ่านการเรียก threestrcpy() ที่ด้านบนของฟังก์ชัน)
      • สร้างหน้าต่างผ่านXPLMCreateWindowEx-
        • ลงทะเบียนการโทรกลับจำนวนหนึ่ง (params.drawWindowFunc และ fiveparams.handleXXXFunc)
        • ตามปกติเมื่อเขียนโค้ดปลั๊กอิน การเรียกกลับเหล่านี้จะถูกลงทะเบียนเมื่อสร้างออบเจ็กต์ (ในกรณีนี้คือหน้าต่าง)
        • เราไม่ได้ระบุค่า refcon เนื่องจากปลั๊กอินของเราจะทำสิ่งเดียวกันเสมอ โดยจะพิมพ์ว่า "hello world" เสมอ
    • คืนค่าเป็นจริงเพื่อระบุว่าโหลดสำเร็จ (หากเราคืนค่าเท็จ เนื่องจากหน้าต่างของเราเป็น NULL เราจะถูกยกเลิกการโหลดทันที)
  • XPluginStop()
    • ทำความสะอาดหน้าต่างที่เราสร้างขึ้น (รหัสหน้าต่างที่เราได้รับXPLMCreateWindowEx-
    • นี่คือในทางเทคนิคไม่จำเป็น เพราะ SDK จะทำเช่นนั้นบังคับทำลายหน้าต่างใดๆ ที่เราไม่สามารถล้างข้อมูลได้เมื่อปลั๊กอินของเราไม่ได้โหลด แต่เป็นแนวปฏิบัติที่ดี
  • XPluginEnable(), XPluginDisable() และ XPluginReceiveMessage()
    • จะต้องระบุการเรียกกลับ "stub" เหล่านี้ แม้ว่าเราจะไม่ต้องการให้ดำเนินการใดๆ ก็ตาม
  • หน้าต่างที่ลงทะเบียนไว้จะเรียกกลับ,draw_hello_world()
    • ก่อนที่การวาดภาพใดๆ จะเกิดขึ้น เราต้องเรียกXPLMSetGraphicsState- (การไม่ทำเช่นนั้นหมายความว่าคุณจะวาดในสถานะใดก็ตามที่ไดรเวอร์ OpenGL อยู่ในสถานะสุดท้าย ซึ่งอาจแตกต่างกันระหว่างการทำงานของโปรแกรมจำลอง หรือแม้แต่เฟรมต่อเฟรม
    • เราจะค้นหาขอบเขตของหน้าต่างใน SDK ในกรณีที่มีการย้ายหรือปรับขนาดตั้งแต่เฟรมที่แล้ว (เนื่องจากหน้าต่างมีรูปแบบเหมือนกับหน้าต่าง X-Plane 11 ที่เป็นค่าเริ่มต้น จึงสามารถเคลื่อนย้ายได้อย่างอิสระ และปรับขนาดภายในขีดจำกัดที่เรากำหนดไว้ในการโทรของเราXPLMSetWindowResizingLimits() เมื่อเราสร้างหน้าต่างขึ้นมา)
    • XPLMDrawString() วาดภาพข้อความขั้นสุดท้าย โปรดทราบว่าเราสามารถได้ใช้โค้ด OpenGL แบบดิบเพื่อใช้งานสิ่งนี้ แต่ไม่จำเป็นต้องใช้เนื่องจาก SDK สามารถจัดการการวาดข้อความได้

แนวทางการออกแบบปลั๊กอิน

การเขียนปลั๊กอิน X-Plane นั้นแตกต่างจากการเขียนแอปพลิเคชันทั่วไป ปลั๊กอินคือแขกภายใน X-Plane และปลั๊กอินที่ออกแบบผิดสามารถทำลายประสิทธิภาพของโปรแกรมจำลองได้

ปลั๊กอินทำงานพร้อมกันโดยสัมพันธ์กันเสมอ ไม่มีการขนานหรือมัลติเธรด หากเราต้องการเธรดหรือกระบวนการแยกต่างหากเพื่อรักษาประสิทธิภาพของโปรแกรมจำลองในขณะทำงาน เราจะต้องนำสิ่งนี้ไปใช้ด้วยตนเอง Xplane จัดการปลั๊กอินแต่ละตัวตามลำดับ โดยจะไม่เรียกใช้ปลั๊กอินมากกว่าหนึ่งตัวในเวลาเดียวกัน มันเรียกกันแบบโรบินตัวกลม

ต่อไปนี้เป็นรายการแนวทางในการออกแบบปลั๊กอิน

ทำความเข้าใจการใช้ทรัพยากรของปลั๊กอิน

ขั้นตอนแรกที่สำคัญที่สุดในการสร้างปลั๊กอินคือการทำความเข้าใจว่าปลั๊กอินที่ใช้งานอยู่มีค่าใช้จ่ายเท่าใด พิจารณา:

  • ปลั๊กอินของฉันต้องทำการคำนวณใดๆ ที่ใช้เวลานานมากจนจะทำให้ประสิทธิภาพของโปรแกรมจำลองลดลงโดยการปิดซิมหรือไม่ โปรดจำไว้ว่าเครื่องจำลองจะดำเนินการทั้งหมดภายใน 50 มิลลิวินาทีที่ 20 เฟรมต่อวินาที หากเราปิดเครื่องจำลองไว้อีก 15 ms เราจะทำให้เครื่องจำลองช้าลงเป็น 15 fps
  • ปลั๊กอินของฉันทำการคำนวณที่เกิดขึ้นบ่อยมากและใช้เวลานานจนต้องใช้เปอร์เซ็นต์ของ CPU หรือไม่ ตัวอย่างเช่น การคำนวณ 2 ms ทุกๆ 10 ms จะใช้ CPU 20% ทันที เพื่อป้องกันการชะลอตัวของ X-Plane 20% งานจะต้องทำงานน้อยลงหรือใช้เวลาน้อยลงในแต่ละครั้งที่ทำงาน
  • ปลั๊กอินของฉันทำ I/O ที่ใช้เวลานานในการดำเนินการให้เสร็จสิ้นและ/หรือต้องทำบ่อยครั้งหรือไม่?

ปลั๊กอินแชร์ทรัพยากรกับเครื่องจำลอง โดยปกติแล้ว X-Plane จะใช้แบนด์วิธของ CPU, หน่วยความจำ และกราฟิกที่มีอยู่ทั้งหมดในการทำงาน (แม้ว่าจะถูกผูกไว้ด้วยแบนด์วิดท์เดียวเท่านั้น ซึ่งแตกต่างกันไปในแต่ละเครื่อง) การใช้ทรัพยากรที่ไม่ใช่ I/O จากปลั๊กอินจะนำออกจากตัวจำลองโดยตรง

โครงสร้างปลั๊กอินเป็นเครื่องของรัฐและตัวจัดการเหตุการณ์

ปลั๊กอินจะประกอบด้วยชุดการโทรกลับ การประมวลผลที่ใช้เวลานานจะส่งผลเสียต่อประสิทธิภาพของโปรแกรมจำลอง หากเป็นไปได้ ให้จัดโครงสร้างปลั๊กอินเป็นเครื่องสถานะและ/หรือชุดตัวจัดการเหตุการณ์ สิ่งนี้ช่วยให้คุณควบคุมการไหลของโปรแกรมโดยไม่ต้องรันโค้ดเป็นระยะเวลานานโดยไม่หยุดชะงัก

รูปวาดและ UI ควรแสดงถึงสถานะ

ด้วยโปรแกรมทั่วไป เรามักจะสามารถวาดไปที่หน้าจอได้ทุกเมื่อที่สะดวกสำหรับเรา ตัวอย่างเช่น เราสามารถวาดไปที่หน้าจอได้ทันทีเมื่อเราได้รับการคลิกเมาส์หรือคำนวณค่าเสร็จแล้ว

ด้วยปลั๊กอินนี่ไม่ใช่กรณี ปลั๊กอินสามารถวาดเพื่อตอบสนองคำขอวาดจากเครื่องจำลองเท่านั้น การโทรกลับเหล่านี้เกิดขึ้นที่ความถี่สูง ด้วยเหตุนี้ โค้ดที่ปกติจะวาดในโปรแกรมทั่วไปจำเป็นต้องบันทึกข้อมูลที่จะทำให้ตัวจัดการการดึงวาดแตกต่างออกไป หน้าจอทั้งหมดจะถูกวาดใหม่ทุกเฟรมของซิม ดังนั้นตัวจัดการการวาดจึงต้องวาดข้อมูลนั้นต่อไปจนกว่าเราจะต้องการให้มันหายไป

มีข้อดีบางประการในการเขียนโปรแกรมเช่นนี้ คุณไม่จำเป็นต้องกังวลเกี่ยวกับการวาดอินเทอร์เฟซผู้ใช้ใหม่เมื่อมีเหตุการณ์เกิดขึ้น จะถูกวาดใหม่อย่างต่อเนื่อง โค้ดรูปวาดทำงานตลอดเวลา ดังนั้นปลั๊กอินจะวาดไม่ช้าลงเมื่อเปลี่ยนกราฟิกเป็นประจำหรือสร้างภาพเคลื่อนไหว

ลดเวลาที่ใช้ในการติดต่อกลับครั้งใดครั้งหนึ่ง

ในขณะที่การโทรกลับกำลังทำงานอยู่ จะไม่สามารถเรียกใช้การโทรกลับอื่นได้ และเครื่องจำลองไม่สามารถทำงานได้ พยายามลดเวลาที่ใช้ในการโทรกลับให้เหลือน้อยที่สุดเพื่อให้เครื่องจำลองทำงานได้อย่างรวดเร็ว แบ่งส่วนของโค้ดที่ช้าออก

ลดงานยุ่งให้เหลือน้อยที่สุด

เมื่องานพื้นฐานที่เป็นไปได้ขึ้นอยู่กับอินพุตของผู้ใช้แทนที่จะเป็นตัวจับเวลา เนื่องจากกิจกรรมของผู้ใช้เกิดขึ้นไม่บ่อย (และเฉพาะเมื่อผู้ใช้กำลังทำอะไรบางอย่าง) ลองใช้ช่วงเวลาตัวจับเวลาที่ยาวที่สุดที่ยอมรับได้ การโทรกลับบ่อยเกินไปจะทำให้ CPU ซึ่งเป็นทรัพยากรที่มีค่าที่สุดของ X-Plane สิ้นเปลือง อย่ากำหนดเวลาให้โทรกลับทุกครั้งที่ซิมวาดใหม่ เว้นแต่เราจำเป็นต้องรันจริงๆ ทุกครั้งที่ซิมดึง (เช่น เพื่อตั้งค่ากล้อง) เมื่อเป็นไปได้ ให้โทรกลับตามระยะเวลาจริง ปิดการใช้งานการโทรกลับที่ไม่จำเป็น

สำรวจข้อมูลเมื่อจำเป็นเท่านั้น

อย่าอ่านข้อมูลจากซิมซ้ำๆ หากสำเนาแคชใช้งานได้ การอ่านข้อมูลจากซิมนั้นรวดเร็วมาก แต่ภายในการโทรกลับเพียงครั้งเดียว ข้อมูลแทบจะไม่สามารถเปลี่ยนแปลงได้อย่างแน่นอน

ข้อมูลแคชเพื่อให้บรรลุเป้าหมายข้างต้น

บันทึกค่าที่มีราคาแพงในการคำนวณเพื่อให้การโทรกลับรวดเร็ว โดยเฉพาะอย่างยิ่ง ตรวจสอบให้แน่ใจว่าคุณไม่ได้คำนวณค่าโดยไม่จำเป็นในการเรียกกลับแบบดึง เนื่องจากจะทำงานบ่อยมาก ค่าแคชและคำนวณใหม่เมื่อมีการเปลี่ยนแปลง แทนที่จะคำนวณใหม่ทุกครั้งที่จำเป็น

I/O – ใช้ I/O แบบไม่บล็อก/อะซิงค์/ซ้อนทับ หรือใช้เธรดแยก

หากปลั๊กอินใช้เวลาส่วนใหญ่ในการทำ I/O (ไฟล์ เครือข่าย หรืออื่นๆ) ให้ใช้ API ที่ไม่รอให้ I/O เสร็จสิ้นก่อนจึงจะกลับมา หรือสร้างเธรดแยกต่างหากที่สามารถเรียกรูทีน I/O ได้

ใช้ I/O ที่ไม่บล็อกหรือทับซ้อนกันหรือเธรด

หากปลั๊กอินทำ I/O จำนวนมาก ให้พิจารณาใช้การเรียก I/O ที่ไม่บล็อกหรือทับซ้อนกันหรืออะซิงโครนัสเพื่อให้การโทรกลับรวดเร็ว การบล็อกในการเรียกกลับสำหรับ I/O จะบล็อกตัวจำลองทั้งหมด ส่งผลให้อัตราเฟรมเสียหาย และสิ้นเปลืองรอบของ CPU

อีกกลยุทธ์หนึ่งคือการใช้ I/O การบล็อกเธรดและรันเธรดผู้ปฏิบัติงานแยกต่างหาก

การอ้างอิงปลั๊กอินพื้นฐาน

สถาปัตยกรรม

ปลั๊กอินถูกนำมาใช้เป็น DLL ปลั๊กอินเชื่อมโยงกับตัวจัดการปลั๊กอิน (ซึ่งเป็น DLL ด้วย) เพื่อเรียกใช้ฟังก์ชันในปลั๊กอิน API SDK ซึ่งจะจัดการเครื่องจำลอง ปลั๊กอินใช้การโทรกลับห้าครั้งผ่านฟังก์ชันที่ส่งออก และยังสามารถให้ตัวชี้ฟังก์ชันเพิ่มเติมสำหรับการลงทะเบียนการโทรกลับผ่านการเรียก API

สภาพแวดล้อมการสร้างปลั๊กอิน

ปลั๊กอิน Mac คือไลบรารีที่มีปลั๊กอินที่จำเป็นในการส่งออก พวกเขาลิงก์อย่างหนักกับ XPLM.framework และไลบรารีอื่นๆ หากจำเป็น สัญลักษณ์หลักไม่ได้ใช้

ปลั๊กอินสำหรับพีซีคือ DLL ที่มีปลั๊กอินที่จำเป็นในการส่งออก ไม่ได้ใช้ฟังก์ชันการแนบเธรด ฯลฯ พวกเขาเชื่อมโยงอย่างหนักกับ XPLM_64.dll และไลบรารีอื่น ๆ หากจำเป็น

การโทรกลับที่จำเป็น

มีการเรียกกลับห้ารายการที่คุณต้องใช้ในปลั๊กอินผ่าน DLL ที่ส่งออก

XPluginStart

PLUGIN_API int XPluginStart (ถ่าน * outName, ถ่าน * outSignature, ถ่าน * outDescription);
  • คำอธิบาย
    • ฟังก์ชันนี้ถูกเรียกโดย X-Plane ทันทีหลังจากโหลด DLL ของปลั๊กอินแล้ว
    • ดำเนินการใดๆ ที่จำเป็นสำหรับปลั๊กอิน ซึ่งรวมถึงการสร้างอินเทอร์เฟซผู้ใช้ การติดตั้งการโทรกลับที่ลงทะเบียนไว้ การจัดสรรทรัพยากร ฯลฯ
    • คัดลอกสตริง C ที่สิ้นสุดด้วยค่า null ซึ่งแต่ละสตริงน้อยกว่า 256 อักขระลงในบัฟเฟอร์ทั้งสามที่ส่งผ่านเข้ามา
    • หากคุณส่งคืนความสำเร็จ (1) ปลั๊กอินจะได้รับการติดต่อกลับเพิ่มเติม หากคุณส่งคืนความล้มเหลว (0) ปลั๊กอินจะถูกยกเลิกการโหลดทันทีโดยไม่มีการเรียกกลับเพิ่มเติม ในกรณีที่เกิดความล้มเหลว ปลั๊กอินจะอยู่ในสถานะปิดใช้งานหลังจากการเรียกนี้
  • ข้อโต้แย้ง
    • outName: ตัวชี้ไปยังบัฟเฟอร์ เติมบัฟเฟอร์นี้ด้วยชื่อปลั๊กอินที่มนุษย์สามารถอ่านได้
    • outSignature: ตัวชี้ไปยังบัฟเฟอร์ เติมบัฟเฟอร์นี้ด้วยลายเซ็นของปลั๊กอิน (ไม่ซ้ำกันทั่วโลก) ตามแบบแผน ให้เริ่มปลั๊กอินนี้ด้วยชื่อองค์กรเพื่อป้องกันการชนกัน
    • outDescription: ตัวชี้ไปยังบัฟเฟอร์ หากโหลดปลั๊กอินสำเร็จ ให้กรอกบัฟเฟอร์นี้ด้วยคำอธิบายของปลั๊กอินที่มนุษย์สามารถอ่านได้ หากไม่สามารถโหลดปลั๊กอินได้ ให้กรอกคำอธิบายถึงปัญหาที่เกิดขึ้น
  • ค่าที่ส่งคืน: 1 หากโหลดปลั๊กอินสำเร็จ มิฉะนั้นจะเป็น 0

XPluginStop

PLUGIN_API เป็นโมฆะ XPluginStop (เป็นโมฆะ);
  • คำอธิบาย:
    • ฟังก์ชันนี้ถูกเรียกโดย X-Plane ก่อนที่ DLL จะถูกยกเลิกการโหลด ปลั๊กอินจะถูกปิดใช้งาน (หากเปิดใช้งาน) ก่อนที่จะเรียกใช้รูทีนนี้
    • ยกเลิกการลงทะเบียนการโทรกลับใด ๆ ที่สามารถยกเลิกการลงทะเบียนได้ กำจัดออบเจ็กต์หรือทรัพยากรใด ๆ และล้างการจัดสรรทั้งหมดที่ทำโดยปลั๊กอิน หลังจากที่คุณกลับมา DLL ของปลั๊กอินจะถูกยกเลิกการโหลด
  • ข้อโต้แย้ง: ไม่มี
  • ค่าส่งคืน: ไม่มี

XPluginเปิดใช้งาน

PLUGIN_API int XPluginEnable (เป็นโมฆะ);
  • คำอธิบาย:
    • ฟังก์ชันนี้ถูกเรียกโดย X-Plane ก่อนที่จะเปิดใช้งานปลั๊กอิน ปลั๊กอินจะไม่ได้รับการติดต่อกลับใดๆ จนกว่าจะเปิดใช้งานปลั๊กอิน และ UI ของปลั๊กอินจะถูกซ่อนและ/หรือปิดใช้งาน
    • ปลั๊กอินจะถูกเปิดใช้งานหลังจากโหลดปลั๊กอินทั้งหมด เว้นแต่ว่าปลั๊กอินจะถูกปิดใช้งานในระหว่างการรัน X-Plane ครั้งล่าสุด (และข้อมูลนี้ถูกบันทึกไว้ในการตั้งค่า) หรือปลั๊กอินทั้งหมดถูกปิดใช้งานโดยผู้ใช้เมื่อเริ่มต้นระบบ หากผู้ใช้เปิดใช้งานปลั๊กอินด้วยตนเอง การเรียกกลับนี้จะถูกเรียกเช่นกัน XPluginEnable() จะไม่ถูกเรียกสองครั้งติดต่อกันหากไม่มีการเรียก XPluginDisable()
    • ควรใช้การโทรกลับนี้เพื่อจัดสรรทรัพยากรใดๆ ที่ปลั๊กอินรักษาไว้ในขณะที่เปิดใช้งาน หากปลั๊กอินเปิดเธรด ให้เริ่มเธรด หากปลั๊กอินใช้เครือข่าย ให้เริ่มการสื่อสารผ่านเครือข่าย
    • คุณควรจัดโครงสร้างการใช้ทรัพยากรของปลั๊กอินเพื่อให้ปลั๊กอินมีค่าใช้จ่ายน้อยที่สุดในการทำงานในขณะที่ปิดใช้งานโดยการจัดสรรทรัพยากรที่มีราคาแพงเมื่อเปิดใช้งานแทนที่จะเป็นเมื่อไรโหลดแล้ว-
  • ข้อโต้แย้ง: ไม่มี
  • ค่าที่ส่งคืน: 1 หากปลั๊กอินเริ่มทำงานได้สำเร็จ มิฉะนั้นจะเป็น 0

XPluginปิดการใช้งาน

PLUGIN_API เป็นโมฆะ XPluginDisable (เป็นโมฆะ);
  • คำอธิบาย:
    • ฟังก์ชันนี้ถูกเรียกโดย X-Plane ก่อนที่ปลั๊กอินจะถูกปิดใช้งาน เมื่อปิดใช้งานปลั๊กอิน มันจะไม่ได้รับการติดต่อกลับใดๆ และ UI ของปลั๊กอินจะถูกซ่อนและ/หรือปิดใช้งาน
    • ปลั๊กอินจะถูกปิดใช้งานก่อนที่จะยกเลิกการโหลดหรือหลังจากที่ผู้ใช้ปิดใช้งานแล้ว มันจะไม่ถูกยกเลิกการโหลดจนกว่าจะปิดการใช้งานแล้ว
    • จัดสรรทรัพยากรที่สำคัญและเตรียมที่จะไม่ได้รับการติดต่อกลับใดๆ เป็นระยะเวลานาน
  • ข้อโต้แย้ง: ไม่มี
  • ค่าส่งคืน: ไม่มี

XPluginReceiveMessage

PLUGIN_API เป็นโมฆะ XPluginReceiveMessage (XPLMPluginIDinFrom, int inMessage, โมฆะ * inParam);
  • คำอธิบาย:
    • ฟังก์ชันนี้ถูกเรียกใช้โดยตัวจัดการปลั๊กอินเมื่อมีการส่งข้อความไปยังปลั๊กอิน คุณจะได้รับทั้งข้อความที่ส่งไปยังปลั๊กอินของคุณโดยเฉพาะและข้อความที่เผยแพร่ไปยังปลั๊กอินทั้งหมด
    • ข้อความเฉพาะจะถูกส่งจาก X-Plane และอธิบายไว้ในเอกสารประกอบการส่งข้อความปลั๊กอิน พารามิเตอร์ที่ส่งจะแตกต่างกันไปขึ้นอยู่กับข้อความ ปลั๊กอินอาจกำหนดข้อความส่วนตัวของตนเองที่จะส่ง หากคุณได้รับข้อความที่คุณไม่รู้จัก คุณควรเพิกเฉยต่อข้อความนั้น
    • หมายเหตุ: ใน SDK เวอร์ชันเก่า inMessage ได้รับการประกาศเป็นประเภท “long” ข้อความนี้เป็นและจะเป็นจำนวนเต็มที่ลงนามแบบ 32 บิตที่ต่ำกว่า 32 และ 64 บิตสำหรับทุกแพลตฟอร์ม การเปลี่ยนประเภท C จาก long เป็น int คือการทำให้ส่วนหัวปลอดภัยสำหรับคอมไพเลอร์ 64 บิต int คือ 32 บิตสำหรับคอมไพเลอร์ทั้งหมดที่เข้ากันได้กับปลั๊กอิน X-Plane แต่ชนิดข้อมูลแบบยาวคือ 32 หรือ 64 บิต ขึ้นอยู่กับ ABI และแพลตฟอร์มและคอมไพเลอร์ จึงไม่ปลอดภัยในการใช้งาน
  • ข้อโต้แย้ง:
    • inFrom: ID ของปลั๊กอินที่ส่งข้อความ
    • inMessage: จำนวนเต็มที่ระบุข้อความที่ส่ง
    • inParam: ตัวชี้ไปยังข้อมูลที่เฉพาะเจาะจงกับข้อความ
  • ค่าส่งคืน: ไม่มี
การพัฒนาปลั๊กอิน - นักพัฒนา X-Plane (2024)

References

Top Articles
Latest Posts
Article information

Author: Patricia Veum II

Last Updated:

Views: 5886

Rating: 4.3 / 5 (44 voted)

Reviews: 83% of readers found this page helpful

Author information

Name: Patricia Veum II

Birthday: 1994-12-16

Address: 2064 Little Summit, Goldieton, MS 97651-0862

Phone: +6873952696715

Job: Principal Officer

Hobby: Rafting, Cabaret, Candle making, Jigsaw puzzles, Inline skating, Magic, Graffiti

Introduction: My name is Patricia Veum II, I am a vast, combative, smiling, famous, inexpensive, zealous, sparkling person who loves writing and wants to share my knowledge and understanding with you.