2010-05-09 34 views
6

Tôi có một dự án C++ sử dụng trình phân tích cú pháp bison C. Các phân tích cú pháp C sử dụng một cấu trúc của con trỏ hàm để gọi chức năng mà tạo nút AST thích hợp khi tác phẩm được giảm bằng cách bò rừng:C chức năng gọi lại được xác định trong một không gian tên chưa đặt tên?

typedef void Node; 
struct Actions { 
    Node *(*newIntLit)(int val); 
    Node *(*newAsgnExpr)(Node *left, Node *right); 
    /* ... */ 
}; 

Bây giờ, trong ++ phần C của dự án, tôi điền vào những gợi ý

class AstNode { 
    /* ... */ 
}; 
class IntLit : public AstNode { 
    /* ... */ 
}; 

extern "C" { 
    Node *newIntLit(int val) { 
    return (Node*)new IntLit(val); 
    } 

    /* ... */ 
} 

Actions createActions() { 
    Actions a; 
    a.newIntLit = &newIntLit; 
    /* ... */ 
    return a; 
} 

Bây giờ lý do duy nhất tôi đặt chúng trong extern "C" là bởi vì tôi muốn họ có các quy ước gọi điện C. Nhưng tối ưu, tôi muốn tên của họ vẫn bị xáo trộn. Họ không bao giờ được gọi là by-name từ mã C, vì vậy tên mangling không phải là một vấn đề. Việc khiến chúng bị xáo trộn sẽ tránh xung đột tên, vì một số hành động được gọi là error và hàm gọi lại C++ có tên xấu như sau để tránh xung đột tên với các mô-đun khác.

extern "C" { 
    void uglyNameError(char const *str) { 
    /* ... */ 
    } 

    /* ... */ 
} 

a.error = &uglyNameError; 

tôi tự hỏi liệu nó có thể là có thể bằng cách chỉ đơn thuần đưa ra các loại chức năng C liên kết

extern "C" void fty(char const *str); 
namespace { 
    fty error; /* Declared! But i can i define it with that type!? */ 
} 

Bất kỳ ý tưởng? Tôi đang tìm kiếm các giải pháp Standard-C++.

+0

Bạn không thể biên dịch đầu ra Bison thành mã C++, do đó tránh được vấn đề hoàn toàn? –

+0

@Konrad đồng nghiệp của tôi nói rằng chế độ bison C++ không tốt để làm việc, và vì vậy chúng tôi làm điều đó với C thuần túy và tóm tắt, vì vậy cùng với máy quét tạo nên một thư viện C thuần túy. –

Trả lời

3

Tôi không gặp sự cố. Từ khóa bên ngoài không ảnh hưởng đến quy ước gọi, chỉ là tên được trình bày cho trình liên kết. Một hàm được viết bằng C++ không phải là một phương thức cá thể vẫn là __cdecl, có hoặc không có extern "C". Hơn nữa, miễn là bạn giữ createActions() trong cùng một tệp mã nguồn, các hàm này không cần liên kết bên ngoài. Bạn có thể khai báo chúng tĩnh hoặc đặt chúng trong một không gian tên không tên để tránh xung đột.

+2

Ah, tôi có thể tạo ra 'tĩnh'. Ý tưởng hay, tại sao tôi không nghĩ về điều đó :) Tôi chỉ nghĩ về các không gian tên không tên, nhưng điều đó sẽ không làm bất cứ điều gì để liên kết của họ và sẽ không ngăn chặn các xung đột cho các hàm 'extern" C "'. Nhưng 'tĩnh' thực sự có thể hoạt động! Đối với các phần còn lại của câu trả lời của bạn: Nó có thể tạo sự khác biệt để gọi quy ước nếu việc thực hiện mong muốn làm như vậy. Tôi muốn không phụ thuộc vào bất kỳ thực hiện cụ thể, vì vậy tôi đã làm cho họ 'extern" C "'. –

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