C ++ 0x keynote (0x) describes something that looks good:
1. Local callCode:
// Use local object:X;A;STD::String s("ABC");//...X.F(A,S);
2. Use the remote proxy wrapper layer:
// Use remote object: Proxy< X > X ; X . Connect ( "My_host" ); A ; STD :: String s ( "ABC" ); //... X . F ( A , S );
Can a remote call be completed using only one packaging layer? From the current C ++ perspective, it is basically impossible. Today, we suddenly thought we could use aspect C ++ to generate code, because aspect C ++ also generated some simple metadata when generating code, you can obtain the function prototype and parameter type in the function. According to the 0x description, I wrote a simple test code:
# Include <string> # include <iostream> # include <sstream> # include <vector> Using namespace STD ; Class Loginservice { Public : Virtual Bool Login ( Const String & Name , Const String & Password , String & Session ) = 0 ; Virtual Void Logout ( Const String & Session ) = 0 ;}; Class Remotecall { Public : Bool Connect ( Const Char * Host , Unsigned short Port ){ Cout< "Connect success" < Endl ; Return True ;} Bool Send ( Const Char * P , Size_t Len ){ Cout < "Send :" < Endl ; Cout < String ( P , Len ) < Endl ; Return True ;} Bool Recv ( Char * P , Size_t Len ){ Return True ;}}; Class Remoteloginservice: Public Loginservice , Public Remotecall { Public : Virtual Bool Login ( Const String & Name, Const String & Password , String & Session ){ Return False ;} Virtual Void Logout ( Const String & Session ){}}; Int Main ( Int Argc , Char * Argv []) { Remoteloginservice RLS ; RLS. Connect ( "Localhost" , 3957 ); String session ; RLS . Login ( "Lijie" , "Lijie" , Session); RLS . Logout ( Session ); Return 0 ;}
The goal is to add a remote call function for remoteloginservice. Of course, because remotecall is not implemented here, you only need to serialize the Call correctly to achieve the goal. After this aspect is completed, it is as follows:
Aspect remote { Pointcut remote_class () = "Remotecall" ; Pointcut remote_call () = Derived ( Remote_class ())&&! Remote_class (); Pointcut virtual_methods () = "%...: % (...)" ; Advice ( Remote_call ())&& Execution( Virtual_methods ()): Before (){ Stringstream SS ; SS < "\ Tcall :" < Joinpoint :: Signature () < Endl ; SS < "\ Targuments :" ; For ( Size_t I = 0 ; I < Joinpoint :: ARGs (); ++ I ){ String ARG ( Tjp-> Argtype ( I )); If ( ARG . Find ( "Basic_string" )! = ARG . NPOs ){ SS <*( String*) Tjp -> ARG ( I ) < "|" ;}} String send_str = SS . Str (); Tjp -> Target ()-> Send( Send_str . C_str (), Send_str . Size ());} Advice ( Remote_call ())&& Execution ( Virtual_methods ()): After (){ Vector< Char > Buffer ( 1024 , '\ 0' ); Tjp -> Target ()-> Recv (&(* Buffer . Begin()), Buffer . Size ()); // Parse the received data and write the remote call result to the memory indicated by tjp-> result () }};
It matches all classes derived from remotecall, and adds Remote Call code and call result processing code to each of its methods. Generate and compile the program. The output is as follows:
Connect success
Send:
Call: bool remoteloginservice: Login (const: STD: basic_string <char >&, const: STD: basic_string <char >&,: STD :: basic_string <char> &)
Arguments: Lijie |
Send:
Call: void remoteloginservice: Logout (const: STD: basic_string <char> &)
Arguments: |
Because each parameter value is fully serialized, the first target-generating Remote Call code-is complete.
For the next goal, how can I write the Log service? The server needs to start a service and register each service interface.
To achieve this goal, aspect C ++ needs to provide types and names at the class and method level, but aspect C ++ does not provide more convenience in this respect, currently, only method information can be obtained when a method is executed. The "meta information" generated by the method is too simple, and each independent structure is implemented for efficiency consideration, structure members are mostly static, so we cannot use a suitable interface for reflection. We hope to add these features in the future.