2010-10-19 15 views
7

Tôi đã có một DLL không được quản lý C++ mà tôi cần gọi từ một ứng dụng Windows Mobile C#.Chuyển chuỗi C# vào một DLL C không được quản lý trong Windows Mobile

Tôi đã có trình bao bọc C# và nó hoạt động độc đáo trên máy tính để bàn. Tôi có thể gọi các hàm DLL từ một chương trình C# trên máy tính để bàn và truyền các chuỗi xung quanh mà không có vấn đề gì.

Tuy nhiên, khi tôi biên dịch lib và trình bao bọc cho nền tảng di động, tôi gặp lỗi trong dòng DllImport nói rằng CharSet.ANSI không được nhận dạng. Các tùy chọn duy nhất tôi được phép viết là CharSet.Auto và CharSet.Unicode.

Vấn đề là, bất kể cài đặt này, các chuỗi được nhận trong các hàm C++ là các chuỗi char rộng và không phải là các chuỗi ký tự đơn giản mà chúng mong đợi.

Chúng ta có thể sử dụng wcstombs() để dịch tất cả các chuỗi vào đầu mỗi C++ chức năng, nhưng tôi không muốn thay đổi lib đến mức độ như vậy ...

Có cách nào để sửa chữa marshalling giữa C# và C hoạt động với .NET Compact Framework?

+0

[Social.msdn] (http://social.msdn.microsoft.com/Forums/en-US/netfxcompact/thread/4aed0776-638a-4fde-ad61-e2462b39a961) nói không :( – GSerg

Trả lời

6

Không, không có.

Microsoft documentation quy định rằng:

[...] .NET Compact Framework chỉ hỗ trợ Unicode, và hậu quả là chỉ bao gồm các CharSet.Unicode (và CharSet.Auto mà bằng Unicode) giá trị, và không không hỗ trợ bất kỳ mệnh đề nào của câu lệnh khai báo . Điều này có nghĩa là tài sản ExactSpelling cũng không được hỗ trợ .

Do vậy, nếu hàm DLL của bạn hy vọng một chuỗi ANSI, bạn sẽ cần để thực hiện việc chuyển đổi trong DLL, hoặc chuyển đổi chuỗi thành một mảng byte sử dụng getBytes quá tải phương pháp của ASCIIEncoding lớp, trước khi gọi hàm, vì .NET Compact Framework sẽ luôn chuyển con trỏ tới chuỗi Unicode. [...]

Giải pháp là:

Chức năng trong DLL

int MARSHALMOBILEDLL_API testString(const char* value); 
const char* MARSHALMOBILEDLL_API testReturnString(const char* value); 

Wrapper

[DllImport("marshalMobileDll.dll")] 
public static extern int testString(byte[] value); 

[DllImport("marshalMobileDll.dll")] 
public static extern System.IntPtr testReturnString(byte[] value); 

Calling Mã

string s1 = "1234567"; 
int v = Wrapper.testString(Encoding.ASCII.GetBytes(s1)); 

string s2 = "abcdef"; 
IntPtr ps3 = Wrapper.testReturnString(Encoding.ASCII.GetBytes(s2)); 
string s3 = IntPtrToString(ps3); 


private string IntPtrToString(IntPtr intPtr) 
{ 
    string retVal = ""; 

    byte b = 0; 
    int i = 0; 
    while ((b = Marshal.ReadByte(intPtr, i++)) != 0) 
    { 
    retVal += Convert.ToChar(b); 
    } 
    return retVal; 
} 
+0

Cuối cùng! Chuyển đổi rõ ràng thực sự có vẻ là giải pháp duy nhất có thể ... Cảm ơn bạn rất nhiều, nó hoạt động rất tốt ngay bây giờ! – matpop

2

Windows CE có xu hướng thiên về Unicode (hầu hết các API Win32 thậm chí không có ANSI tương đương). Như vậy, CF không thực sự làm tốt với ANSI hoặc là nó cần một chút "trợ giúp" để làm cho nó đúng.

Bạn có thể nói với marshaler mà bạn muốn vượt qua các dữ liệu như single-byte, giá trị null chấm dứt bằng cách sử dụng các thuộc tính MarshalAs (the MSDN docs hiển thị rõ ràng nó được hỗ trợ trong CF), một cái gì đó dọc theo những dòng:

[DllImport("mydll.dll", SetLastError = true)] 
public static extern void Foo([MarshalAs(UnmanagedType.LPStr)]string myString); 
+0

không may, MarshalAs không được hỗ trợ theo Compact Framework – tato

+0

Theo ai? MarshalAs chắc chắn nhất * được * hỗ trợ. Tôi sử dụng nó khá thường xuyên và tôi hầu như không làm gì ngoài việc làm CF. – ctacke

+0

MSDN nói được hỗ trợ từ 3,5 SP1 –