2013-07-31 45 views
5

Chúng tôi đang sử dụng bộ đệm giao thức (2.4.1) trong một hệ thống nhúng kích thước trung bình w/C# một mã C++. Chúng tôi sử dụng các protobuf để tách riêng các lớp được quản lý và bản địa của chúng ta một cách dễ dàng để duy trì lớp tuần tự hóa (Đối với những người tò mò, chúng tôi đã sử dụng Pinvoke, nhưng chúng tôi cũng phải chạy mã gốc trong một quá trình riêng biệt trên thử nghiệm/mô phỏng).- tạo các truy nhập không nội tuyến

Hệ thống của chúng tôi có một số tệp DLL và tôi có mã protobuf gốc được tạo trong tệp DLL của chính nó để các phần khác của hệ thống không thể liên kết trực tiếp trong mã được tạo.

Vấn đề tôi đang gặp là tất cả các bộ truy xuất được tạo ra là inline, ví dụ:

inline const ::MyProtoClassName::MyField& MyProtoClassName::myfield() const 
{ 
    return myfield_ != NULL ? *myfield_ : *default_instance_->myfield_; 
} 

sử dụng API được tạo ra có kích thước (của default_instance_ 'được dereferenced và truy cập nếu đặc biệt này trường không được đặt). Điều này có nghĩa là tôi không thể liên kết (lnk2001) bất kỳ khách hàng nào sử dụng accessors vì không có biểu tượng default_instance_

Tôi nghĩ trường hợp sử dụng điển hình cho ProtoBufs sẽ có liên kết thành phần trong chính mã protobuf được tạo ra (sau khi tất cả , đây chủ yếu là lớp tuần tự hóa cho các hệ thống phân tán), nhưng

Tôi tự hỏi nếu có một công cụ biên dịch để thay đổi hành vi nội tuyến mà tôi đã bỏ qua. (Có tất cả người truy cập được xác định trong tệp CC, chứ không phải H)

Cảm ơn!


  • Cảm ơn @g-makulik! Hình như câu trả lời là khoảng 30 dòng trong mã ProtoC, tôi chỉ cần không nhìn thấy nó :)

    • < xem câu trả lời của ông dưới đây để biết phần lớn các giải pháp> Điều này cũng sẽ giúp bạn, mặc dù.

Như đã đề cập trong một số ghi thay đổi Kenton, thêm điều này gây ra nhiều cảnh báo (C4251, c4275) liên quan đến các lớp học cơ sở mà không phải là cũng DLLEXPORT'd

với cách ProtoBufs được thực hiện, và các lớp protobuf là tất cả các mẫu, các cảnh báo này là lành tính. Để bỏ qua chúng một cách rõ ràng (ví dụ như KHÔNG cần phải tắt cảnh báo cho tất cả các máy khách) Tôi đã sử dụng cách tiếp cận hơi khó khăn này:

-wrapper cho tệp protobuf.h mà eveyone bao gồm.(Không ai bao gồm các tập tin H thực được tạo ra)

#pragma once 
    #pragma warning(push) 
    #pragma warning(disable:4251) 
    #pragma warning(disable:4275) 
    // include the protobuf generated code; but exclude the warn c4251, c4275 
    // these relate to the dll exported  
    #include "yourProtoFile.h" 
    #pragma warning(pop) 

và một tập tin wrapper C (file CC protobuf thực không có trong dự án của tôi -> không được xây dựng trực tiếp)

#include "MyProtoFile_WRAPPER.h" 
#include "MyProtoFile.cc" 
+0

Tôi thấy trong mã ProtoC rằng gen mã chức năng nội tuyến dường như chỉ được gọi từ lệnh GenerateHeader (...) ... nhưng tôi hy vọng internet đã giải quyết được vấn đề này trước tôi! :) – mike

Trả lời

4

Tôi nghĩ rằng liên kết này có thể trả lời câu hỏi của bạn: Protobuf with MSVC: how to export generated Message

Trích từ Kenon Varga (Phụ trách dự án của google protobuf):

Nếu bạn gọi protoc như:

protoc --cpp_out = dllexport_decl = MY_EXPORT_MACRO: path/to/đầu ra/dir myproto.proto

sau đó nó sẽ tạo ra mã với MY_EXPORT_MACRO trong tất cả các nơi phải. Tuy nhiên, tùy chọn này chưa hoàn thành - hiện tại không có cách nào để ép buộc tệp .pb.h thành #include một tiêu đề xác định MY_EXPORT_MACRO. Tôi mở bản vá để sửa lỗi này. Hoặc, bạn có thể sử dụng một hack để làm việc xung quanh nó, chẳng hạn như thêm #include qua một số loại xử lý văn bản sau khi kết thúc protoc, hoặc có thể di chuyển tệp .pb.h sang .pb2.h và thay thế tệp .pb.h bằng một trong những đầu tiên bao gồm tiêu đề của bạn sau đó bao gồm các .pb2.h ...

Và additonally để trang trải các bất toàn đề cập (Trích từ Aron Bierbaum):

Chúng tôi hiện có được khắc phục hạn chế này bằng cách buộc tiêu đề để được bao gồm bằng cách sử dụng cờ dòng lệnh của trình biên dịch:

Windows:/FIproject/Con fig.h
Linux: Dự án -gồm/config.h

LƯU Ý:
Sử dụng từ khóa inline không nên có liên quan trong trường hợp này (tức thêm __declspec dllexport/__declspec dllimport thuộc tính được đặt trên phương thức truy cập). Mỗi định nghĩa nó lên đến trình biên dịch để chức năng nội tuyến hay không. Tất nhiên, việc xem thuộc tính __declspec dllexport hoặc __declspec dllimport là contradictionary cho nội tuyến.

+0

@ike THX để chấp nhận. Chỉ cần googled một chút về chủ đề ;-). Có thể bạn nên cập nhật câu hỏi của mình với giải pháp cuối cùng mà bạn đã đưa ra. Nó cung cấp các tùy chọn định dạng tốt hơn ít nhất ... –

+0

Vui lòng xem câu trả lời của tôi trong câu hỏi của tôi cho các nhận xét của tôi - vì vậy tôi có thể định dạng chúng một cách dễ đọc. – mike

+0

@mike Điều đó có vẻ tốt hơn nhiều! –