การตั้งค่าเส้นทางของ Native Library สำหรับ DllImport บน Mono สำหรับ Mac

รหัสที่ฉันกำลังย้ายไปยัง Mono สำหรับ Mac เรียกเข้าสู่ไลบรารี C ++ ที่ไม่มีการจัดการ บน Mac ฉันได้ย้ายไลบรารี่ที่ไม่มีการจัดการของเราไปไว้ใน Framework แล้ว (น่าเสียดายที่กระบวนการ Build ของเราอนุญาตให้คอมไพล์เป็น Framework เท่านั้น ไม่ใช่เป็น dylib) ใน Mono ฉันได้ตั้งค่าขั้นตอนการสร้างโพสต์ในโครงการของฉันเพื่อคัดลอกไฟล์ Framework ถัดจากแอปที่สร้างขึ้น

แต่เมื่อ P/Invoke เข้าสู่ dll นี้ ฉันจะได้รับข้อยกเว้น DllNotFound ฉันอ่าน Mono Interop Wiki อย่างละเอียด และดูเหมือนว่า P/Inrigg บน Mono จะดูเฉพาะตำแหน่งเท่านั้น ชี้ไปที่ตัวแปรสภาพแวดล้อม DYLD_* และไดเรกทอรีปัจจุบันไม่อยู่ในเส้นทางการค้นหา เมื่อฉันคัดลอก Framework ไปที่ /Library/Frameworks การเรียก P/Inake ของฉันทำงานได้ดี แต่ฉันต้องการให้ไฟล์ Framework ของฉันปรากฏถัดจาก App และไม่ได้อยู่ใน /Library/Frameworks

ฉันพยายามเพิ่มไดเร็กทอรีการทำงานปัจจุบันให้กับตัวแปรสภาพแวดล้อม DYLD_FRAMEWORK_PATH ในโค้ดของฉันก่อนที่จะทำการเรียก P/Invoke ใดๆ แต่เนมสเปซ System.Environment มีฟังก์ชันการทำงานที่จำกัดบน Mono สำหรับ Mac และไม่รองรับการรับหรือการตั้งค่าตัวแปรสภาพแวดล้อม

มีวิธีใดบ้างที่ฉันสามารถเก็บไฟล์ Framework ของฉันไว้ข้าง App และยังสามารถ P/Inrigg ได้หรือไม่


person Shivaprasad    schedule 11.10.2012    source แหล่งที่มา
comment
คุณกำลังบอกว่า System.Environment.SetEnvironmentVariable ใช้ไม่ได้กับ Mono ใช่หรือไม่   -  person David Heffernan    schedule 11.10.2012


คำตอบ (1)


เราจะแยกคำถามออกเป็นสองคำถาม: วิธีตั้งค่าตัวแปรสภาพแวดล้อม และวิธีรวมเฟรมเวิร์กเนทิฟในแอปพลิเคชัน MonoMac

การตั้งค่าตัวแปรสภาพแวดล้อม

คุณสามารถตั้งค่าตัวแปรสภาพแวดล้อมได้ในส่วน LSEnvironment ของ Info.plist ของแอปพลิเคชันของคุณ ดังนี้:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
            <dict>
            <key>CFBundleIdentifier</key>
            <string>com.yourcompany.TableViewTest</string>
            <key>CFBundleName</key>
            <string>TableViewTest2</string>
            <key>CFBundleVersion</key>
            <string>1</string>
            <key>LSMinimumSystemVersion</key>
            <string>10.6</string>
            <key>NSMainNibFile</key>
            <string>MainMenu</string>
            <key>NSPrincipalClass</key>
            <string>NSApplication</string>
            <key>LSEnvironment</key>
            <dict>
                    <key>Foo</key>
                    <string>Bar</string>
            </dict>
    </dict>
    </plist>

ดูเหมือนว่าจะต้องแก้ไขไฟล์นั้นด้วยตนเองหนึ่งครั้งและเพิ่มตัวแปรสภาพแวดล้อมอย่างน้อยหนึ่งตัว

ไฟล์จะถูกสร้างขึ้นโดยอัตโนมัติโดย MonoDevelop ดังนั้นสิ่งที่คุณต้องทำคือเพิ่มส่วน LSEnvironment

หลังจากนั้นคุณสามารถแก้ไขได้ใน MonoDevelop: ไปที่ตัวเลือกโครงการ "แอปพลิเคชัน Mac OS X" "ขั้นสูง"

การรวม Native Frameworks ในแอปพลิเคชัน MonoMac

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

ฉันสร้างแอปพลิเคชันทดสอบ ขนาดเล็ก ซึ่งรวมเฟรมเวิร์กทั้งในภาษาเนทีฟเข้าด้วยกัน แอปพลิเคชัน Objective C และใน MonoMac

สิ่งแรกที่คุณต้องทำคือรวมเฟรมเวิร์กของคุณเข้ากับแอป ขณะนี้ยังไม่มีวิธีการทำเช่นนี้โดยอัตโนมัติใน MonoDevelop ดังนั้นคุณต้องคัดลอกไฟล์ด้วยตนเองหรือใช้สคริปต์หลังการสร้าง (ดู copy-framework.sh ในตัวอย่างของฉัน)

ฉันอยากจะแนะนำให้ใส่เฟรมเวิร์กลงใน YourApp.app/Contents/Frameworks/YourFramework.framework เพราะนั่นคือวิธีที่ XCode จัดการมัน โปรดดูเอกสารของ Apple ด้วย

หากต้องการอ้างอิงไลบรารีภายในชุดแอปพลิเคชันของคุณ คุณสามารถใช้ `@executable_path' (ดูที่ หน้าคน dyld)

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

    <configuration>
       <dllmap dll="TestFramework" target="@executable_path/../Frameworks/TestFramework.framework/TestFramework" />
     </configuration>

หากไลบรารีจริงภายในเฟรมเวิร์กของคุณเริ่มต้นด้วย lib หรือลงท้ายด้วย .so / .dylib คุณต้องระบุชื่อนั้น (เช่น dllmap ข้างต้นจะไม่สร้างไฟล์ TestFramework.framework/libTestFramework.dylib เป็นต้น) นี่เป็นข้อผิดพลาดใน Mono ซึ่งฉันเพิ่งแก้ไขไปแล้ว

person Martin Baulig    schedule 11.10.2012
comment
วิธีการนี้ใช้งานได้เมื่อฉันให้เส้นทางแบบเต็มแก่แอปของฉันในตัวแปรสภาพแวดล้อม แต่จะล้มเหลวหากฉันพยายามให้เส้นทางสัมพัทธ์จากสิ่งที่ควรเป็นไดเร็กทอรีการทำงานปัจจุบัน เมื่อฉันทำการดีบักเพิ่มเติมในแอปของฉัน ฉันพบว่า cwd ถูกตั้งค่าเป็น / มีวิธีใดบ้างที่ฉันสามารถกำหนดเส้นทางไปยังแอปของฉันโดยไม่ต้องฮาร์ดโค้ดได้ - person Shivaprasad; 12.10.2012
comment
คุณสามารถแทนที่ไฟล์เริ่มต้น YourApp.app/Contents/MacOS/YourApp ด้วยเชลล์สคริปต์หรือแก้ไขไฟล์ที่สร้างโดย MonoDevelop (github.com/mono/monodevelop/blob/master/main/build/MacOSX/) อย่างไรก็ตาม ฉันคิดว่าฉันเพิ่งพบวิธีที่ดีกว่าและสะอาดกว่ามากในการทำเช่นนี้ ให้ฉันทดสอบอย่างรวดเร็ว จากนั้นฉันจะอัปเดตคำตอบของฉันด้วย - person Martin Baulig; 12.10.2012
comment
โอเค จริงๆ แล้วมีวิธีที่สะอาดและง่ายดายในการทำเช่นนี้ เพียงแค่ต้องแก้ไขข้อบกพร่องใน Mono อย่างรวดเร็วเพื่อให้คุณใช้งานได้ - person Martin Baulig; 13.10.2012