Following the tutorial I successfully generated the code I expected with protocol buffers:
protoc service.proto --proto_path="../proto/" --cpp_out="../cxx/gen/" --plugin=protoc-gen-grpc=`which grpc_cpp_plugin`
The models are generated as usable classes without error, but the service implementation differs from the one described in the above tutorial. The proto file looks like this:
syntax = "proto3";
option cc_enable_arenas = true;
option cc_generic_services = true;
package my_package;
message Service_slot{...}
message Slot_status{...}
message Slot_request{...}
message Service_slot{...}
service My_service{
rpc add_slot(Service_slot) returns (Slot_status) {}
rpc update_slot(Service_slot) returns (Slot_status) {}
rpc request_action(Slot_request) returns (Slot_status) {}
}
What I could identify as a service looks like this(in service.pb.h):
class My_service: public ::google::protobuf::Service {
protected:
// This class should be treated as an abstract interface.
inline My_service() {};
public:
virtual ~My_service();
typedef My_service_Stub Stub;
static const ::google::protobuf::ServiceDescriptor* descriptor();
virtual void add_slot(::google::protobuf::RpcController* controller,
const ::my_package::Service_slot* request,
::my_package::Slot_status* response,
::google::protobuf::Closure* done);
//... (others left out for clairty)
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(My_service);
};
but it's nothing like what' described in the tutorial. Not even sure how to provide those arguments.
I've done this in Java, and there the server I implemented was based on a classname ending with grpc, but I found nothing like this here.
What have I found, and how can I understand it? I believe this must be a base service implementation, and the actual server I need to implement is not here.
Maybe I generated the proto files wrong? What can I do to correct it?
I was missing the --grpc_out="../cxx/gen" argument.
With the command
protoc service.proto --proto_path="../proto/" --cpp_out="../cxx/gen/" --grpc_out="../cxx/gen --plugin=protoc-gen-grpc=`which grpc_cpp_plugin`
The service code now generates into the service.grpc.pb.cc file.
Related
I'm using gRPC for communication between several services written in Python, C++ and RESTfull (https://github.com/grpc-ecosystem/grpc-gateway)
I have a gRPC server in Python, gRPC clients in Python and C++ and I have RESTfull service using grpc-gateway. For all of them I use one single .proto file (to avoid duplication).
But .proto file contains several statements which I don't want to use for generation of stubs for particular languages. For example I don't need to import and use grpc-gateway statements like I mentioned in comments in following .proto file:
syntax = "proto3";
package calculator;
option go_package = "github.com/grpc_api_for_software/grpc_client_web";
import "google/api/annotations.proto";
import "google/protobuf/empty.proto";
import "protoc-gen-openapiv2/options/annotations.proto"; // I DONT NEED IT IN C++
// I DONT NEED FOLLOWING OPTION IN C++
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
info: {
version: "1.0";
};
external_docs: {
url: "some_url";
description: "gRPC-gateway some test";
}
schemes: HTTPS;
};
service Calculator {
rpc NewTestSet(google.protobuf.Empty) returns (NewTestSet_response) {}
rpc ChangeSettings(ChangeSettings_request) returns (google.protobuf.Empty) {}
rpc DoMath(DoMath_request) returns (DoMath_response) {
// I DONT NEED FOLLOWING OPTION IN C++
option (google.api.http) = {
post: "/domath"
body: "*"
};
}
rpc ListToDict(ListToDict_request) returns (ListToDict_response) {}
rpc DictToList(DictToList_request) returns (DictToList_response) {}
}
...
Is it possible to ignore certain statements for compiling code of .proto in particular languages?
I was looking at creating a service locator that I would also like to provide "NULL" implementations of the services it provides. How would you go about parsing the Interface and auto generating an implementation? What tools would you use - say with CMake? Basically, I am trying to avoid having to write something like:
class IAudio
{
virtual void playSound(SoundId Id) = 0;
....
};
***** Following is the boilerplate I would like to avoid *****
class NullAudio : IAudio
{
void playSound(SoundId) override { /* Does Nothing */ }
....
};
I can't seem to find any examples from my google searches for automatic code generation - they all turn up things that reference code completion in editors. I would even consider running a python script that looks for files starting with I - like IAudio.hpp, parses it and writes out a file if that is the common way to do this.
Thanks!
I think I figured it out. Write a small tool to do what I want, configure CMake to compile it first, and then have CMake run the tool with add_custom_command.
I am trying to use an AppService in winrt/c++, following the github sample in C++/Cx. I always get the "AppUnavailable" result. I have confirmed I connect to the correct service name and have the correct family package name.
My appxmanifest:
<Extensions>
<uap:Extension Category="windows.appService" EntryPoint="BlankApp5.Inventory">
<uap3:AppService Name="com.microsoft.inventory" uap4:SupportsMultipleInstances="true"/>
</uap:Extension>
</Extensions>
My provider header file (in Mainpage.h):
namespace winrt::BlankApp5::implementation
{
class Inventory : public InventoryT<Inventory> {
public:
virtual void Run(IBackgroundTaskInstance taskInstance);
private:
BackgroundTaskDeferral mDef;
AppServiceConnection appServiceConnection;
};
My MainPage.idl file:
[default_interface]
runtimeclass Inventory : Windows.ApplicationModel.Background.IBackgroundTask
{
void Run(Windows.ApplicationModel.Background.IBackgroundTaskInstance taskInstance);
}
During IDL generation I get the following warning:
[msg]A member name has been qualified with an interface name because name collisions occurred across interface members on a runtime class. [context]"Run" has been renamed as "BlankApp5.IInventory.Run" on runtime class "BlankApp5.Inventory"
I am a bit worried that the Inventory::Run gets stripped by the linker, as it is not used internally in the serviceprovider, but I have no other idea why it doesnt work. The provider and client are in two different solutions and have no references between each other, but I assume this is not needed. The service prodiver has been deployed, but not launched. Launching makes no difference.
You needn't declare the void Run(Windows.ApplicationModel.Background.IBackgroundTaskInstance taskInstance); in your idl file, because you implement IBackgroundTask and a void Run is declared implicitly.
I have implemented a service in C++ using gSoap. I have created it from a multiple existing WSDL files.
And now I need to give a definition to every virtual method of the service.
Let's take a look at one generated method declaration in the file soapMyServiceService.h:
///
/// Service operations (you should define these):
/// Note: compile with -DWITH_PURE_VIRTUAL for pure virtual methods
///
/// Web service operation 'Initialize' (returns error code or SOAP_OK)
virtual int Initialize(_ns5__Initialize *ns5__Initialize, _ns5__InitializeResponse *ns5__InitializeResponse);
Actually, I was expecting to get :
virtial string Initialize(int var_a , int var_b , string var_c);
But now, I need to implement it what I got generated and return the SOAP code :
int MyService::Initialize(_ns5__Initialize *ns5__Initialize, _ns5__InitializeResponse *ns5__InitializeResponse)
{
// HOW can I get here the received values for that I can able to implement my logic?
return SOAP_OK;
}
How can I get the received values ( the values sent by the client for var_a, var_b, and var_c) and then set for him the returned for the string and in the same time return the error code...
How do you normally implement the logic of the services?
Thank you.
In your service method implementation MyService::Initialize(_ns5__Initialize *ns5__Initialize, _ns5__InitializeResponse *ns5__InitializeResponse)
the last argument is the response argument all the rest are input argument, here you have only one input parameter that is of type _ns5__Initialize which probably wud be a structure, if you access its member, you will get all the input parameters of the request.
I am trying to expose a C++ library to python using boost-python. The library actually wraps an underlying C api, so uses raw pointers a lot.
// implementation of function that creates a Request object
inline Request Service::createRequest(const char* operation) const
{
blpapi_Request_t *request;
ExceptionUtil::throwOnError(
blpapi_Service_createRequest(d_handle, &request, operation)
);
return Request(request);
}
// request.h
class Request {
blpapi_Request_t *d_handle;
Element d_elements;
Request& operator=(const Request& rhs); // not implemented
public:
explicit Request(blpapi_Request_t *handle);
Request(RequestRef ref);
Request(Request &src);
};
// request.cpp
BOOST_PYTHON_MODULE(request)
{
class_<blpapi_Request_t>;
class_<Request, boost::noncopyable>("Request", init<blpapi_Request_t *>())
.def(init<Request&>())
;
}
Although request.cpp compiles successfully, when I try and use the object I get the following error:
// error output
TypeError: No to_python (by-value) converter found for C++ type: class Request
In-order to call this the python code looks like:
from session import *
from service import *
from request import *
so = SessionOptions()
so.setServerHost('localhost')
so.setServerPort(8194)
session = Session(so)
# start sesssion
if not session.start():
print 'Failed to start session'
raise Exception
if not session.openService('//blp/refdata'):
print 'Failed to open service //blp/refdata'
raise Exception
service = session.getService('//blp/refdata')
request = service.createRequest('ReferenceDataRequest')
The other objects (SessionOptions, Session, Service) etc are also c++ objects that I have successfully created boost-python wrappers for.
As I understand from the boost-python docs this has something to do with passing a raw pointer around, but I don't really understand what else I should do ...
Your class_<blpapi_Request_t>; does not declare anything; is that code the correct version?
If so, then update it:
class_<blpapi_Request_t>("blpapi_Request_t");
That said, what that error indicates is that you are trying to use the Request object with an automatic conversion to a python object which has not been defined.
The reason you get this error is because you have wrapped Request as boost::noncopyable, then provided a factory method which returns a Request object by value; the boost::noncopyable means no copy constructors are generated and therefore there's no automatic to-python converter.
Two ways out of this: one is to remove the noncopyable hint; the other would be to register a converter which takes a C++ Request and returns a Python Request object. Do you really need the noncopyable semantics for Request?