วิธีการออกแบบโปรแกรม C ++ เพื่ออนุญาตให้นำเข้าฟังก์ชั่นรันไทม์?


10

วันนี้ฉันอยากถามคุณเกี่ยวกับความสามารถของ C ++ ในการตระหนักถึงสถาปัตยกรรมซอฟต์แวร์เฉพาะ

แน่นอนฉันใช้การค้นหา แต่ไม่พบคำตอบที่เชื่อมโยงโดยตรง

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

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

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

เพื่อให้คุณเข้าใจมากขึ้นนี่เป็นตัวอย่างที่ง่ายมาก:

<COMPONENT name="Main">
  <COMPONENT name="A">
    <FUNCTION name="A1" path="lib/functionA1" />
  </COMPONENT>
  <COMPONENT name="B">
    <FUNCTION name="B1" path="lib/functionB1" />
    <FUNCTION name="B2" path="lib/functionB2" />
  </COMPONENT>
  <CONNECTIONS>
    <CONNECTOR source="A1" target="B1" />
    <CONNECTOR source="B1" target="B2" />
  </CONNECTIONS>        
</COMPONENT>

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

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

ขอบคุณล่วงหน้า!

ไชโยโอลิเวอร์


C ++ มีพอยน์เตอร์ของฟังก์ชันและวัตถุของฟังก์ชัน ฟังก์ชั่นทั้งหมดได้รวบรวมไว้ในไฟล์เรียกทำงานหรือไม่หรืออยู่ในไลบรารีแบบไดนามิก (บนแพลตฟอร์มใด)
Caleth

1
คำถามคือกว้างเกินไปในแง่ที่ว่ามันมักจะต้องใช้ในระดับมหาวิทยาลัยในสาขาวิศวกรรมไฟฟ้าทั้ง / [อิเล็กทรอนิกส์แบบอัตโนมัติ (EDA)] ( en.wikipedia.org/wiki/Electronic_design_automation ) หรือวิศวกรรมเครื่องกล / การออกแบบด้วยคอมพิวเตอร์ (CAD) เมื่อเทียบกับการพูดเรียกห้องสมุดแบบไดนามิก C / C ++ เป็นอย่างมากง่ายดูC เรียกประชุมสำหรับ x86 อาจต้องจัดการสแต็ก (ผ่านตัวชี้สแต็ก CPU) และค่าการลงทะเบียน CPU แม้ว่า

1
ฟังก์ชั่นการโหลดแบบไดนามิกไม่รองรับภาษา C ++ คุณจะต้องดูบางอย่างเฉพาะแพลตฟอร์ม เช่นคอมไพเลอร์ C ++ บน Windows ควรสนับสนุน Windows DLLs ซึ่งรองรับรูปแบบการสะท้อน
Simon B

ใน C ++ เป็นการยากที่จะเรียกใช้ฟังก์ชันที่ไม่รู้จักลายเซ็น (อาร์กิวเมนต์และชนิดส่งคืน) ณ เวลารวบรวม ในการทำเช่นนั้นคุณต้องรู้ว่าการเรียกฟังก์ชั่นทำงานที่ระดับการประกอบของแพลตฟอร์มที่คุณเลือกได้อย่างไร
Bart van Ingen Schenau

2
วิธีที่ฉันจะแก้ปัญหานี้คือการรวบรวมรหัส c ++ ที่สร้างล่ามสำหรับภาษาใด ๆ ที่สนับสนุนคำสั่ง eval แก้ไขปัญหาบางอย่างโดยใช้ c ++ : P โปรดคิดว่าทำไมจึงไม่ดีพอและอัปเดตคำถาม ช่วยเมื่อความต้องการที่แท้จริงมีความชัดเจน
candied_orange

คำตอบ:


13

ใน C ++ มาตรฐานบริสุทธิ์คุณไม่สามารถ "อนุญาตให้นำเข้าฟังก์ชั่นรันไทม์"; ตามมาตรฐานชุดของฟังก์ชั่น C ++ นั้นเป็นที่รู้จักกันในเวลาบิลด์ (ในทางปฏิบัติ, ลิงก์เวลา) ตั้งแต่การแก้ไขจากการรวมกันของหน่วยการแปลทั้งหมดที่เขียนโปรแกรมของคุณ

ในทางปฏิบัติมากที่สุดของเวลา (ไม่รวมระบบฝังตัว) ของ C ++ โปรแกรมวิ่งข้างต้นบางระบบปฏิบัติการ อ่านระบบปฏิบัติการ: สามชิ้นง่ายสำหรับภาพรวมที่ดี

หลายระบบปฏิบัติการที่ทันสมัยช่วยให้โหลดแบบไดนามิกของปลั๊กอิน POSIX สะดุดตาระบุ&dlopen dlsymWindows มีบางอย่างที่แตกต่างกันLoadLibrary(และรุ่นการเชื่อมโยงที่ต่ำกว่าคุณต้องใส่คำอธิบายประกอบฟังก์ชั่นที่เกี่ยวข้องจัดเตรียมหรือใช้โดยปลั๊กอินอย่างชัดเจน) BTW บน Linux คุณสามารถdlopenปลั๊กอินจำนวนมาก (ดูที่manydl.cโปรแกรมของฉันด้วยความอดทนพอที่จะสามารถสร้างปลั๊กอินที่โหลดได้เกือบล้านรายการ) ดังนั้นสิ่งที่ XML ของคุณสามารถผลักดันการโหลดปลั๊กอิน คำอธิบายส่วนประกอบหลายส่วน / ตัวเชื่อมต่อหลายส่วนทำให้ฉันนึกถึงสัญญาณและช่องเสียบ Qt (ซึ่งต้องใช้mocตัวประมวลผลล่วงหน้าคุณอาจต้องการอะไรแบบนั้นด้วย)

ส่วนใหญ่ C ++ การใช้งานที่ใช้ชื่อ mangling ด้วยเหตุนี้คุณจะประกาศได้ดีขึ้นว่าเป็นextern "C"ฟังก์ชั่นที่เกี่ยวข้องกับปลั๊กอิน (และกำหนดไว้ในพวกเขาและเข้าถึงได้dlsymจากโปรแกรมหลัก) อ่านC ++ dlopen mini HowTo (สำหรับ Linux อย่างน้อย)

BTW, QtและPOCOเป็นเฟรมเวิร์ก C ++ ที่ให้แนวทางแบบพกพาและระดับสูงกว่าสำหรับปลั๊กอิน และlibffiช่วยให้คุณสามารถเรียกฟังก์ชั่นที่มีลายเซ็นเป็นที่รู้จักกันเท่านั้นที่รันไทม์

ความเป็นไปได้อีกอย่างคือการฝังล่ามไว้ในโปรแกรมของคุณ ( เช่นLuaหรือGuile ) (หรือเขียนของคุณเองเช่นเดียวกับ Emacs) นี่คือการตัดสินใจออกแบบสถาปัตยกรรมที่แข็งแกร่ง คุณอาจต้องการอ่านเสียงกระเพื่อมในชิ้นเล็กและการเขียนโปรแกรมภาษาปฏิบัติเพื่อเพิ่มเติม

มีหลากหลายวิธีหรือหลายวิธี คุณสามารถใช้ห้องสมุดรวบรวม JIT (เช่นlibgccjitหรือasmjit) คุณสามารถสร้างรหัส C และ C ++ ในรันไทม์ในไฟล์ชั่วคราวรวบรวมเป็นปลั๊กอินชั่วคราวและโหลดปลั๊กอินนั้นแบบไดนามิก (ฉันใช้วิธีการดังกล่าวในGCC MELT )

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

อ่านยังเกี่ยวกับการปรับปรุงซอฟแวร์แบบไดนามิก

ขอให้สังเกตว่าภาษาการเขียนโปรแกรมบางภาษาโดยเฉพาะCommon Lisp (และSmalltalk ) นั้นมีความเป็นมิตรกับแนวคิดการนำเข้าฟังก์ชันรันไทม์ SBCLเป็นการใช้งานซอฟต์แวร์ฟรีของ Common LISP และคอมไพล์ไปยังรหัสเครื่องทุกการตอบสนอง REPL (และยังสามารถเก็บรวบรวมรหัสเครื่องได้และยังสามารถบันทึกไฟล์ภาพหลักทั้งหมดซึ่งสามารถเริ่มต้นใหม่ได้อย่างง่ายดายในภายหลัง)


3

เห็นได้ชัดว่าคุณกำลังพยายามที่จะย้อนกลับสไตล์ของคุณเองของซอฟต์แวร์ประเภท Simulink หรือ LabVIEW แต่ด้วยองค์ประกอบ XML ที่ไม่บริสุทธิ์

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

ไม่มีกลไกบังคับใช้ภาษาในการทำเช่นนี้แม้แต่กับการสะท้อนดังนั้นคุณจะต้องสร้าง API และส่วนประกอบใด ๆ ที่ต้องการเล่นจะต้องใช้ฟังก์ชั่นหลายอย่างและปฏิบัติตามกฎที่กำหนดโดย API ของคุณ

แต่ละองค์ประกอบจะต้องใช้ชุดฟังก์ชั่นเพื่อทำสิ่งต่าง ๆ เช่น:

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

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

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

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

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

DirectShow เป็น API ที่ทำทุกอย่างที่ฉันอธิบายและสามารถเป็นตัวอย่างที่ดีในการดู


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.