วิธีใช้คลาสที่นำมาใช้ใน exe จาก dll

ฉันกำลังสร้างเอ็นจิ้นเกมที่เรียบง่ายและมีเกมอยู่ในนั้น แนวคิดคือการมีฟังก์ชันการทำงานและลำดับชั้นคลาสพื้นฐานส่วนใหญ่ที่นำมาใช้ในเอ็นจิ้นซึ่งควรเป็น exe จากนั้นจึงมี dll ซึ่งจะใช้เกมเฉพาะตามเครื่องมือที่เอ็นจิ้นมีให้ คล้ายกับกลไกรหัสเช่น idTech4

จากนั้นเอ็นจิ้นจะโหลด dll รับอินสแตนซ์ของเกม ชี้เกมไปยังฟังก์ชันและโครงสร้างข้อมูลใดก็ตามที่เกมต้องการ และวิธีการเรียก เช่น game->update(); บนอินสแตนซ์เกม จนถึงตอนนี้ดีมาก

ฉันต้องการให้สิ่งต่าง ๆ เช่นคลาสพื้นฐานเช่น Entity, Transform, Vector3 ฯลฯ นำไปใช้ในเครื่องยนต์ ในเกมสิ่งที่ฉันต้องการคือได้รับตัวละครของฉันจาก Entity

class Character : public engine::Entity {...};

สิ่งต่าง ๆ เช่นนี้คอมไพล์ได้เลยเนื่องจากฉันรวมส่วนหัวจากเอ็นจิ้นไว้ แต่ไม่ได้เชื่อมโยงเนื่องจากฉันไม่ได้ใช้ไฟล์ obj หรือไฟล์ cpp จากเอ็นจิ้น ฉันรู้ว่าทำไมสิ่งนี้ถึงไม่ทำงาน เท่าที่ฉันรู้ตัวเลือก (สมเหตุสมผล) ของฉันคือ:

  1. ทำให้คลาสเหล่านี้เป็นส่วนหัวเท่านั้น - ด้วยวิธีนี้มันจะคอมไพล์ทุกที่เสมอ

ฉันไม่ต้องการสิ่งนี้เพราะมันจะเพิ่มเวลาในการคอมไพล์ ขนาดไบนารี่ ฯลฯ

  1. ใส่ฟังก์ชันการทำงานทั่วไปลงใน lib หรือ dll

สิ่งนี้จะได้ผล แต่ไฟล์ lib หมายความว่าฉันมีคลาสเดียวกันที่คอมไพล์ (เชื่อมโยง) ทั้งใน exe (เอ็นจิ้น) และ dll (เกม) - มันดูเลอะเทอะ Dll ใช้งานได้ แต่ดูเหมือนว่าจะทำงานหนักมากกับการส่งออกและการนำเข้าทั้งหมดที่ฉันต้องทำกับทั้งเอ็นจิ้นและเกม สิ่งที่สำคัญที่สุดคือ ทั้งแนวทาง lib และ dll ต่างก็มีปัญหาร่วมกัน นั่นคือในระหว่างการพัฒนา ฉันอาจจะต้องย้ายคลาสต่างๆ ไปมาบ่อยครั้ง เนื่องจากลำดับชั้นของคลาสอาจเปลี่ยนแปลงไปมาก เป็นต้น

คำถามของฉันคือ มีวิธีอื่นในการแก้ไขปัญหานี้หรือไม่ สำหรับฉันนี่ดูเหมือนเป็นคุณสมบัติที่มีประโยชน์มากที่จะมีลำดับชั้นของคลาสใน exe ที่ใช้งานได้จาก dll ฉันลองทำสิ่งที่ไร้สาระมาก เช่น ให้ลิงเกอร์ใช้ไฟล์ .obj ที่สร้างขึ้นระหว่างการคอมไพล์เอ็นจิ้น แต่มันก็ไม่ได้ผลเว้นแต่ฉันจะระบุไฟล์ .obj ทั้งหมดทีละไฟล์ (ฉันใช้ Visual Studio 2017)

ฉันไม่ต้องการละทิ้งความเป็นโมดูลาร์ของการออกแบบนี้

แก้ไข: เนื่องจาก dll เป็นแพลตฟอร์มเฉพาะ เราลองพิจารณา Windows กัน (แม้ว่าฉันเดาว่าแพลตฟอร์มอื่นจะคล้ายกัน)


person Aldarrion    schedule 27.04.2017    source แหล่งที่มา
comment
ฉันสับสนเล็กน้อยเกี่ยวกับเอ็นจิ้นที่เป็น exe และเกมเป็น dll คงไม่สมเหตุสมผลกว่านี้ใช่ไหม?   -  person 463035818_is_not_a_number    schedule 27.04.2017


คำตอบ (2)


ดูเหมือนว่าคุณต้องการใช้การโหลดแบบไดนามิก แต่ฉันคิดว่าคุณอาจพลิกสถานการณ์ไปในทางที่ผิด exe มักจะมีรหัสเกมและ .dll มีตรรกะและคลาสของกลไกเกม คุณโหลด .dll ในโค้ด .exe และลงทะเบียนสิ่งต่างๆ กับเอ็นจิ้น เพื่อให้โค้ดเกมของคุณได้รับการอัปเดตและแสดงผล

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

หากฉันคิดว่ามีอะไรแปลกใหม่ ฉันจะโพสต์ไว้ที่นี่ แต่ในระหว่างนี้ เรามีข้อมูลเกี่ยวกับการโหลดแบบไดนามิกเพื่อช่วยคุณในการเริ่มต้น https://en.wikipedia.org/wiki/Dynamic_loading

person MrJman006    schedule 27.04.2017
comment
ในใจของฉัน มันคงจะสมเหตุสมผลที่จะมีเอ็นจิ้นที่ควบคุมลูปเกมหลักโดยที่มันเรียกว่า game->update() หากเกมเป็น exe ทุกคนที่ต้องการสร้างเกมจำเป็นต้องดูแลลูปหลัก การมีเอ็นจิ้นเป็น dll ดูเหมือนจะมีเฟรมเวิร์กมากกว่า ฉันน่าจะเจาะลึกโค้ด IdTech4 และดูว่ามันทำได้อย่างไร ยังไงก็ขอบคุณนะ :) - person Aldarrion; 28.04.2017
comment
ใช่แล้ว เป็นเรื่องดีเสมอที่ได้เห็นว่าโครงการที่ประสบความสำเร็จกำลังทำสิ่งต่าง ๆ เพื่อหาแรงบันดาลใจอย่างไร โปรดทราบว่ามีเว็บไซต์แลกเปลี่ยนสแต็กการพัฒนาเกมซึ่งเนื้อหานี้อาจเหมาะสมกว่า นี่คือคำถามเกี่ยวกับการแยกเอนจิ้นออกจากเกมจากตัวแก้ไขเลเวลที่คุณอาจพบว่าน่าสนใจ gamedev.stackexchange.com/questions/26520/ - person MrJman006; 28.04.2017
comment
คุณถูกต้องในแนวคิดของเอ็นจิ้นที่ต้องมีความทั่วไปเพียงพอที่จะเรียกใช้การอัปเดตในเกม แต่คุณต้องการให้โปรแกรมเมอร์สามารถใช้รหัสเอ็นจิ้นของคุณเป็นอย่างน้อยในการลงทะเบียนอ็อบเจ็กต์ ในการทำเช่นนั้น คุณต้องมีวิธีให้พวกเขาโหลดโค้ดนั้นเพื่อใช้งาน นั่นคือสาเหตุที่มันมักจะอยู่ในรูปแบบ .dll คุณไม่สามารถโหลดจาก .exe ได้ เว้นแต่ว่าคุณกำลังตั้งค่าหน่วยความจำที่ใช้ร่วมกัน - person MrJman006; 28.04.2017
comment
ในตอนท้ายของวัน เรากำลังคุยกันว่าโค้ดเอ็นจิ้นของคุณได้รับการคอมไพล์และโหลดโดยโค้ดอื่น ๆ ที่มีตรรกะของเกมอย่างไร อย่างไรก็ตาม คุณจะบรรลุผลสำเร็จซึ่งไม่เกี่ยวข้องตราบใดที่โปรแกรมเมอร์อิสระสามารถลงทะเบียนวัตถุเกมกับเอ็นจิ้นได้ (ในการตั้งค่าปกติ เอ็นจิ้นใน .dll) หรือสามารถลงทะเบียนสัญญาณเอ็นจิ้นเกมด้วยโค้ดตรรกะของเกมได้ (ฉันเดาได้ดีที่สุดในการออกแบบสิ่งที่คุณ กำลังพยายามที่จะบรรลุ) - person MrJman006; 28.04.2017

Put the common functionality into a lib or a dll.

สิ่งนี้ใช้งานได้ แต่ไฟล์ lib จะหมายความว่าฉันมีคลาสเดียวกันที่คอมไพล์ (เชื่อมโยง) ทั้งใน exe และ dll

ไม่ มันจะไม่ คลาสต่างๆ จะถูกคอมไพล์และพร้อมใช้งานบนไลบรารีที่ใช้ร่วมกัน (.เช่น บน linux, .dll บน windows, .dylib บน mac) และไฟล์ปฏิบัติการของคุณจะเรียกใช้เมธอดเฉพาะ นั้น จากไลบรารีที่ใช้ร่วมกัน มันจะไม่ถูกคอมไพล์อีกครั้งในไฟล์ปฏิบัติการของคุณ

ลองดูกรอบงานหรือไลบรารี ทั้งหมด ใน C++ ที่ได้รับการติดตั้ง:

  • The public part is exposed on the headers
    • __dllexport(true) on the classes / functions.
  • The private part is hidden
    • Private shouldn't even exist on the public headers unless it's a d-ptr
    • https://en.wikipedia.org/wiki/Opaque_pointer
    • สิ่งนี้จะเพิ่มความปลอดภัยมากขึ้นต่อความเข้ากันได้แบบไบนารี
  • ไม่ต้องกังวลกับการเพิ่มเวลาในการโหลดหากคุณใช้วิธีไลบรารีแบบแบ่งใช้ จะไม่มีนัยสำคัญใดๆ
person Tomaz Canabrava    schedule 27.04.2017
comment
ส่วนที่คุณอ้างอิงพูดถึงแนวทาง lib (คงที่) วิธีการแบบไดนามิกมีข้อเสียอื่น ๆ ที่ฉันพูดถึง ขอบคุณ ยังไงก็ตาม ฉันอาจจะเปลี่ยนหลายๆ อย่าง แม้ว่าแนวทางของ IdTech จะดูดีมากก็ตาม - person Aldarrion; 28.04.2017