2013-05-14 14 views
5

Tôi đang cố liên kết một thư viện tĩnh (foo.a) - chứa mã C++ - trong một dự án Xamarin.Android theo sau directions được tìm thấy trong tài liệu của Xamarin. Cả phương pháp "đường dẫn sniffing" cũng như phương thức "Abi element trong tệp dự án" dường như không hoạt động.Xamarin.Android: Làm thế nào để bạn liên kết một thư viện tĩnh?

Sử dụng một trong hai phương pháp tôi nhận được unhandled trường hợp ngoại lệ khi tôi cố gắng để gọi các hàm thư viện:

I/mono(2591): [ERROR] FATAL UNHANDLED EXCEPTION: System.EntryPointNotFoundException: ... 

tôi nên đề cập đến mà tôi đã không có sự cố kết nối và gọi vào thư viện này (xây dựng cho ARMv7, armv7s) với dự án Xamarin.iOS của tôi bằng cách sử dụng phương pháp "đối số mtouch bổ sung" - được mô tả here. Tất cả các DLLImports của tôi đều giống nhau trên các nền tảng ...

[DllImport(Import.lib, CallingConvention=CallingConvention.Cdecl)] 
internal static extern IntPtr FooMethodName(args); 

Vì vậy, tôi thiếu gì?

FYI: Tôi đang sử dụng Xamarin Studio 4.0.5 (xây dựng 4), Xamarin.Android 4.6.4 (Business Edition)

+0

Nó có thể hoạt động nếu bạn DllImport ("__ Internal") – tofutim

Trả lời

7

Tôi nhận ra câu hỏi này là hơn một năm cũ, nhưng vì thời gian gần đây tôi đã phải làm chính xác điều này, và đánh vào đầu của tôi ở cùng một chỗ, tôi sẽ có một đi vào nó anyway ...

TL; DR: bạn không thể liên kết thư viện tĩnh với Xamarin cho Android, bạn chỉ có thể liên kết thư viện động (.so)

Các bước:

  • Nếu thư viện của bạn được viết bằng C, bạn có thể bỏ qua bước đầu tiên. Nhưng nếu lib của bạn được viết bằng C++, trước tiên bạn phải khai báo các hàm được xuất công khai của bạn dưới dạng hàm C trong mã của bạn (nghĩa là bạn phải đặt chúng trong khối #extern "C" {}). Nếu bạn không làm điều này tên chức năng của bạn sẽ bị C++ manglingling tên và Xamarin sẽ không thể tìm thấy chúng.
extern "C" 
{ 
    void my_function(bool someParameter); 
} 
  • Sử dụng Android NDK, biên dịch thư viện của bạn vào một thư viện liên kết động (.so). Một thư viện tĩnh (.a) sẽ không làm. Đây là nơi tôi đánh đầu, vì điều này không rõ ràng từ tài liệu. Thêm vào sự nhầm lẫn, trên IOS chính xác là đối diện: bạn có thể liên kết tĩnh .a libs chỉ ở đó (theo chính sách AppStore).
  • Thực hiện việc này cho mỗi kiến ​​trúc bộ vi xử lý mà bạn muốn hỗ trợ (thông thường, armeabi, armeabi-v7a và x86)
  • Từ đây tôi giả sử bạn có một bộ thư viện .so, một cho mỗi bộ xử lý. Các thư viện đều có tên là libX.so, trong đó X là tên dự án của thư viện của bạn. Ví dụ. "libmylibrary.so".
  • Trong dự án Xamarin Android của bạn, thêm thư mục "libs" bên dưới gốc dự án. (Bạn cũng có thể sử dụng tên khác nếu muốn)
  • Bên dưới thư mục "libs", tạo ba thư mục con, có tên "armeabi", "armeabi-v7a" và "x86" tương ứng. Sao chép một trong các tệp .so của bạn vào từng thư mục con này (thư mục tương ứng với cùng kiến ​​trúc bộ xử lý). Điều này cho phép tính năng Xamarin "path sniffing" sẽ chọn đúng thư viện cho kiến ​​trúc bộ xử lý phù hợp.
  • Bao gồm cả ba.vì vậy các files trong dự án của bạn và cho mỗi một bộ "Xây dựng hành động" tài sản để "AndroidNativeLibrary"
  • Bây giờ thêm chức năng nhập như các phương pháp tĩnh để một lớp học với các DllImport thích Xamarin thuộc tính:
namespace MyApp 
{ 
    public static class MyLibrary 
    { 
     [DllImport("libmylibrary", EntryPoint = "my_function")] 
     public static extern void MyFunction(Boolean someParameter); 
    } 
} 
  • Vậy đó. Bây giờ bạn có thể gọi MyLibrary.MyFunction() từ Xamarin C# code