2009-08-13 46 views
14

Tôi đã gặp vấn đề này khi chuyển đổi con trỏ C++/CLI thành con trỏ C++ gốc. Heres nền: Tôi đang viết một ứng dụng biểu mẫu cửa sổ bằng cách sử dụng C++/CLI. Ứng dụng này thực hiện cuộc gọi vào một số giao diện COM. Khi tạo một thể hiện (bên trong của một C++/CLR lớp) của một đối tượng thông qua giao diện COM, tôi vượt qua trong (void**)(&provider) như là đối số cuối cùng để CoCreateInstance, như trong:Chuyển đổi từ con trỏ C++/CLI sang con trỏ C++ bản địa

HRESULT CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, (void**)(&provider)); 

Tuy nhiên, tôi nhận được lỗi biên dịch: không thể chuyển đổi từ cli::interior_ptr<Type> thành void **. Tôi đã thực hiện một số nghiên cứu về vấn đề này và có vẻ như đó là vấn đề về các loại con trỏ khác nhau trong C++ và C++/CLI. Bất cứ ai có bất kỳ kiến ​​thức về điều này, và có thể là một mẹo về cách nó có thể được cố định? Thanx trước!

Đầu tiên, thanx cho tất cả sự giúp đỡ của bạn!

Như Freich đã đề xuất, tôi đã cố gắng sử dụng pin_ptr, nhưng thay vào đó, trình biên dịch này phàn nàn về các sự cố khi chuyển đổi từ interior_ptr thành pin_ptr. Nếu tôi thay vì cố gắng sử dụng interior_ptr như trong:

pin_ptr<void *> pinnedPtr = &provider; 
CoCreateInstance(CLSID_MSPRProvider, NULL, CLSCTX_LOCAL_SERVER, IID_IMSPRProvider, (void**)pinnedPtr); 

tôi nhận được không thể chuyển đổi interior_ptr-interior_ptr. Tất cả điều này sẽ chuyển sang vấn đề chuyển đổi interior_ptr thành void**. Như thế này: (void**)interiorPtr, trong đó interiorPtr tất nhiên là interior_ptr. Bất kỳ ý tưởng trong này?

Trả lời

10

Tôi tin rằng bạn phải đánh dấu con trỏ là 'ghim' (trong mã được quản lý) và sau đó sao chép byte sang một số vùng bộ nhớ không được quản lý, sau đó sử dụng con trỏ đến đó. Ví dụ, đây là một đoạn mã Tôi đã từng có một nơi nào đó chuyển một con trỏ đến một hệ thống quản lý :: String để một UTF-8 mã hóa không được quản lý std :: string:

std::string managedStringToStlString(System::String ^s) 
{ 
    Encoding ^u8 = Encoding::UTF8; 
    array<unsigned char> ^bytes = u8->GetBytes(s); 
    pin_ptr<unsigned char> pinnedPtr = &bytes[0]; 
    return string((char*)pinnedPtr); 
} 

Lưu ý làm thế nào tôi đã có để có được một con trỏ 'ghim' vào mảng bytes được trả về bởi hàm GetBytes() và sau đó truyền đến char* trước khi chuyển nó tới hàm tạo std::string. Tôi tin rằng điều này là cần thiết để tránh rằng hệ thống con bộ nhớ được quản lý di chuyển mảng bytes xung quanh trong bộ nhớ trong khi tôi đang sao chép các byte vào chuỗi STL.

Trong trường hợp của bạn, hãy thử thay thế

CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, (void**)(&provider)); 

với

pin_ptr<void *> pinnedPtr = &provider; 
CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, (void**)pinnedPtr); 

và xem liệu rằng hoạt động.

+0

Điều này có vẻ nguy hiểm! Tôi đã có một tình huống tương tự (hoặc tương tự) trước đây: Tôi đã tạo một con trỏ được ghim và trả về con trỏ nguyên gốc (như bạn làm), nhưng sau đó đối tượng đã được di chuyển vì hàm đã kết thúc và con trỏ được ghim đã bị xóa, vì vậy đối tượng không còn nữa được ghim và con trỏ gốc không hợp lệ! Điều này có thể hoặc có thể không được nhìn thấy trong khi gỡ lỗi, nhưng chắc chắn nó sẽ xảy ra trong phiên bản phát hành của bạn khi bạn không mong đợi nó. –

+0

@TobiasKnauss constructor 'std :: string :: string (const char *)' tạo ra một bản sao của dữ liệu được tham chiếu, do đó, không sao nếu bộ nhớ tham chiếu không còn được ghim khi hàm thoát. –

3

Đã khá lâu rồi tôi sử dụng C++/CLI, nhưng tôi nghĩ bạn phải ghim con trỏ.

+0

Có một mẫu tiện lợi được gọi là cli :: pin_ptr có thể là những gì cần thiết vì nó được thiết kế để đảm bảo một con trỏ đến một đối tượng được quản lý không được di chuyển xung quanh bởi bộ thu gom rác. –

3

Bộ nhớ có được dự kiến ​​là hợp lệ ngoài cuộc gọi đến CoCreateInstance() không?

Như Frerich và Achim ám chỉ, bạn có thể lấy một con trỏ thô tới bộ nhớ, mà không sợ bộ nhớ được di chuyển, bằng cách "ghim" nó và nhận được một con trỏ bên trong. Bạn thường làm điều này với mẫu pin_ptr (xem bài viết Frerich cho một ví dụ).

Tuy nhiên, pin_ptr chỉ có thể sử dụng được trên ngăn xếp.Bạn không thể sử dụng nó như biến thành viên hoặc toàn cầu, và bạn không thể chuyển nó thành một đối số hoặc giá trị trả về. Bộ nhớ được bỏ ghim khi nó rời khỏi phạm vi.

Vì vậy, nếu bộ nhớ chỉ được yêu cầu hợp lệ trong khi gọi đến CoCreateInstance() thì pin_ptr là cách để đi. Nếu không thì bạn sẽ phải lấy một bản sao của bộ nhớ và vượt qua rằng trên để CoCreateInstance()

Các vấn đề liên quan