Bump gRPC

This commit is contained in:
Changhua
2022-10-15 20:25:42 +08:00
parent 35498520c2
commit ef20038fcd
50 changed files with 1905 additions and 2387 deletions
+166
View File
@@ -0,0 +1,166 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{2fc45612-a106-42d1-871f-1de704095b2c}</ProjectGuid>
<RootNamespace>cpp</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<VcpkgUseStatic>true</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static</VcpkgTriplet>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)/spy;$(SolutionDir)/rpc;C:\Tools\vcpkg\installed\x86-windows-static\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4251</DisableSpecificWarnings>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>$(OutDir)sdk.lib;iphlpapi.lib;wsock32.lib;ws2_32.lib;crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\proto\wcf.grpc.pb.h" />
<ClInclude Include="..\proto\wcf.pb.h" />
<ClInclude Include="..\sdk\sdk.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\proto\wcf.grpc.pb.cc" />
<ClCompile Include="..\proto\wcf.pb.cc" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="..\proto\wcf.proto" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+47
View File
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="proto">
<UniqueIdentifier>{0b2f5211-3264-4e9b-8f6d-9f2b51780156}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\proto\wcf.grpc.pb.h">
<Filter>proto</Filter>
</ClInclude>
<ClInclude Include="..\proto\wcf.pb.h">
<Filter>proto</Filter>
</ClInclude>
<ClInclude Include="..\sdk\sdk.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="..\proto\wcf.grpc.pb.cc">
<Filter>proto</Filter>
</ClCompile>
<ClCompile Include="..\proto\wcf.pb.cc">
<Filter>proto</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\proto\wcf.proto">
<Filter>proto</Filter>
</None>
</ItemGroup>
</Project>
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
+521
View File
@@ -0,0 +1,521 @@
/*
RPC Client
*/
#pragma warning(disable : 4251)
#pragma execution_character_set("utf-8")
#include <memory>
#include <signal.h>
#include <thread>
#include <grpcpp/grpcpp.h>
#include "../proto/wcf.grpc.pb.h"
#include "../sdk/sdk.h"
using namespace std;
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using wcf::Contact;
using wcf::Contacts;
using wcf::DbField;
using wcf::DbNames;
using wcf::DbQuery;
using wcf::DbRow;
using wcf::DbRows;
using wcf::DbTable;
using wcf::DbTables;
using wcf::Empty;
using wcf::ImageMsg;
using wcf::MsgTypes;
using wcf::Response;
using wcf::String;
using wcf::TextMsg;
using wcf::Verification;
using wcf::Wcf;
using wcf::WxMsg;
class WcfClient
{
public:
static WcfClient &Instance(string host_port)
{
static WcfClient instance(grpc::CreateChannel(host_port, grpc::InsecureChannelCredentials()));
return instance;
}
~WcfClient()
{
cout << "~WcfClient()" << endl;
this->DisableRecvMsg();
// WxDestroySDK();
}
int IsLogin()
{
Empty empty;
Response rsp;
ClientContext context;
std::mutex mu;
std::condition_variable cv;
bool done = false;
Status status;
stub_->async()->RpcIsLogin(&context, &empty, &rsp, [&mu, &cv, &done, &status](Status s) {
status = std::move(s);
std::lock_guard<std::mutex> lock(mu);
done = true;
cv.notify_one();
});
std::unique_lock<std::mutex> lock(mu);
cv.wait(lock, [&done] { return done; });
if (!status.ok()) {
cout << "IsLogin rpc failed." << endl;
}
return rsp.status();
}
string GetSelfWxid()
{
Empty empty;
String rsp;
ClientContext context;
std::mutex mu;
std::condition_variable cv;
bool done = false;
Status status;
stub_->async()->RpcGetSelfWxid(&context, &empty, &rsp, [&mu, &cv, &done, &status](Status s) {
status = std::move(s);
std::lock_guard<std::mutex> lock(mu);
done = true;
cv.notify_one();
});
std::unique_lock<std::mutex> lock(mu);
cv.wait(lock, [&done] { return done; });
if (!status.ok()) {
cout << "GetSelfWxid rpc failed." << endl;
}
return rsp.str();
}
void EnableRecvMsg(function<void(WxMsg &)> msg_handle_cb)
{
class Reader : public grpc::ClientReadReactor<WxMsg>
{
public:
Reader(Wcf::Stub *stub, function<void(WxMsg &)> msg_handle_cb)
: msg_handle_cb_(msg_handle_cb)
{
stub->async()->RpcEnableRecvMsg(&context_, &empty_, this);
StartRead(&msg_);
StartCall();
}
void OnReadDone(bool ok) override
{
if (ok) {
try {
msg_handle_cb_(msg_);
} catch (...) {
cout << "OnMsg wrong..." << endl;
}
StartRead(&msg_);
}
}
void OnDone(const Status &s) override
{
unique_lock<mutex> l(mu_);
status_ = s;
done_ = true;
cv_.notify_one();
}
Status Await()
{
unique_lock<mutex> l(mu_);
cv_.wait(l, [this] { return done_; });
return move(status_);
}
private:
Empty empty_;
WxMsg msg_;
ClientContext context_;
mutex mu_;
Status status_;
bool done_ = false;
condition_variable cv_;
function<void(WxMsg &)> msg_handle_cb_;
};
Reader reader(stub_.get(), msg_handle_cb);
Status status = reader.Await();
if (!status.ok()) {
cout << "GetMessage rpc failed." << endl;
}
}
// void EnableRecvMsg(function<void(WxMsg &)> msg_handle_cb) { GetMessage(msg_handle_cb); }
int DisableRecvMsg()
{
Empty empty;
Response rsp;
ClientContext context;
std::mutex mu;
std::condition_variable cv;
bool done = false;
Status status;
stub_->async()->RpcDisableRecvMsg(&context, &empty, &rsp, [&mu, &cv, &done, &status](Status s) {
status = std::move(s);
std::lock_guard<std::mutex> lock(mu);
done = true;
cv.notify_one();
});
std::unique_lock<std::mutex> lock(mu);
cv.wait(lock, [&done] { return done; });
if (!status.ok()) {
cout << "DisableRecvMsg rpc failed." << endl;
}
return rsp.status();
}
int SendTextMsg(string msg, string receiver, string atusers)
{
Response rsp;
ClientContext context;
std::mutex mu;
std::condition_variable cv;
bool done = false;
Status status;
TextMsg t_msg;
t_msg.set_msg(msg);
t_msg.set_receiver(receiver);
t_msg.set_aters(atusers);
stub_->async()->RpcSendTextMsg(&context, &t_msg, &rsp, [&mu, &cv, &done, &status](Status s) {
status = std::move(s);
std::lock_guard<std::mutex> lock(mu);
done = true;
cv.notify_one();
});
std::unique_lock<std::mutex> lock(mu);
cv.wait(lock, [&done] { return done; });
if (!status.ok()) {
cout << "SendTextMsg rpc failed." << endl;
rsp.set_status(-999); // TODO: Unify error code
}
return rsp.status();
}
int SendImageMsg(string path, string receiver)
{
Response rsp;
ClientContext context;
std::mutex mu;
std::condition_variable cv;
bool done = false;
Status status;
ImageMsg i_msg;
i_msg.set_path(path);
i_msg.set_receiver(receiver);
stub_->async()->RpcSendImageMsg(&context, &i_msg, &rsp, [&mu, &cv, &done, &status](Status s) {
status = std::move(s);
std::lock_guard<std::mutex> lock(mu);
done = true;
cv.notify_one();
});
std::unique_lock<std::mutex> lock(mu);
cv.wait(lock, [&done] { return done; });
if (!status.ok()) {
cout << "SendImageMsg rpc failed." << endl;
rsp.set_status(-999); // TODO: Unify error code
}
return rsp.status();
}
MsgTypes GetMsgTypes(void)
{
Empty empty;
MsgTypes mt;
ClientContext context;
std::mutex mu;
std::condition_variable cv;
bool done = false;
Status status;
stub_->async()->RpcGetMsgTypes(&context, &empty, &mt, [&mu, &cv, &done, &status](Status s) {
status = std::move(s);
std::lock_guard<std::mutex> lock(mu);
done = true;
cv.notify_one();
});
std::unique_lock<std::mutex> lock(mu);
cv.wait(lock, [&done] { return done; });
if (!status.ok()) {
cout << "GetMsgTypes rpc failed." << endl;
}
return mt;
}
Contacts GetContacts(void)
{
Empty empty;
Contacts contacts;
ClientContext context;
std::mutex mu;
std::condition_variable cv;
bool done = false;
Status status;
stub_->async()->RpcGetContacts(&context, &empty, &contacts, [&mu, &cv, &done, &status](Status s) {
status = std::move(s);
std::lock_guard<std::mutex> lock(mu);
done = true;
cv.notify_one();
});
std::unique_lock<std::mutex> lock(mu);
cv.wait(lock, [&done] { return done; });
if (!status.ok()) {
cout << "GetContacts rpc failed." << endl;
}
return contacts;
}
DbNames GetDbNames(void)
{
Empty empty;
DbNames names;
ClientContext context;
std::mutex mu;
std::condition_variable cv;
bool done = false;
Status status;
stub_->async()->RpcGetDbNames(&context, &empty, &names, [&mu, &cv, &done, &status](Status s) {
status = std::move(s);
std::lock_guard<std::mutex> lock(mu);
done = true;
cv.notify_one();
});
std::unique_lock<std::mutex> lock(mu);
cv.wait(lock, [&done] { return done; });
if (!status.ok()) {
cout << "GetDbNames rpc failed." << endl;
}
return names;
}
DbTables GetDbTables(string db)
{
DbTables tables;
ClientContext context;
std::mutex mu;
std::condition_variable cv;
bool done = false;
Status status;
String s_db;
s_db.set_str(db);
stub_->async()->RpcGetDbTables(&context, &s_db, &tables, [&mu, &cv, &done, &status](Status s) {
status = std::move(s);
std::lock_guard<std::mutex> lock(mu);
done = true;
cv.notify_one();
});
std::unique_lock<std::mutex> lock(mu);
cv.wait(lock, [&done] { return done; });
if (!status.ok()) {
cout << "GetDbTables rpc failed." << endl;
}
return tables;
}
DbRows ExecDbQuery(string db, string sql)
{
DbRows rows;
ClientContext context;
std::mutex mu;
std::condition_variable cv;
bool done = false;
Status status;
DbQuery query;
query.set_db(db);
query.set_sql(sql);
stub_->async()->RpcExecDbQuery(&context, &query, &rows, [&mu, &cv, &done, &status](Status s) {
status = std::move(s);
std::lock_guard<std::mutex> lock(mu);
done = true;
cv.notify_one();
});
std::unique_lock<std::mutex> lock(mu);
cv.wait(lock, [&done] { return done; });
if (!status.ok()) {
cout << "ExecDbQuery rpc failed." << endl;
}
return rows;
}
int AcceptNewFriend(string v3, string v4)
{
Response rsp;
ClientContext context;
std::mutex mu;
std::condition_variable cv;
bool done = false;
Status status;
Verification v;
v.set_v3(v3);
v.set_v4(v4);
stub_->async()->RpcAcceptNewFriend(&context, &v, &rsp, [&mu, &cv, &done, &status](Status s) {
status = std::move(s);
std::lock_guard<std::mutex> lock(mu);
done = true;
cv.notify_one();
});
std::unique_lock<std::mutex> lock(mu);
cv.wait(lock, [&done] { return done; });
if (!status.ok()) {
cout << "ExecDbQuery rpc failed." << endl;
rsp.set_status(-999); // TODO: Unify error code
}
return rsp.status();
}
private:
unique_ptr<Wcf::Stub> stub_;
WcfClient(shared_ptr<Channel> channel)
: stub_(Wcf::NewStub(channel))
{
WxInitSDK();
}
};
int OnMsg(WxMsg msg)
{
cout << "Got Message: \n"
<< msg.is_self() << ", " << msg.is_group() << ", " << msg.type() << ", " << msg.id() << ", " << msg.xml()
<< ", " << msg.sender() << ", " << msg.roomid() << ", " << msg.content() << endl;
return 0;
}
// volatile bool gKeepRunning = false;
// void handler(int s)
// {
// printf("Caught signal %d\n", s);
// // exit(1);
// gKeepRunning = false;
// }
int main(int argc, char **argv)
{
int ret;
// signal(SIGINT, handler);
WcfClient &client = WcfClient::Instance("localhost:10086");
ret = client.IsLogin();
cout << "IsLogin: " << ret << endl;
cout << "Self Wxid: " << client.GetSelfWxid() << endl;
ret = client.SendTextMsg("来自CPP的消息!", "filehelper", "");
cout << "SendTextMsg: " << ret << endl;
ret = client.SendImageMsg("TEQuant.jpeg", "filehelper");
cout << "SendImageMsg: " << ret << endl;
MsgTypes mts = client.GetMsgTypes();
cout << "GetMsgTypes: " << mts.types_size() << endl;
map<int32_t, string> m(mts.types().begin(), mts.types().end());
for (auto &[k, v] : m) {
cout << k << ": " << v << endl;
}
Contacts cnts = client.GetContacts();
cout << "GetContacts: " << cnts.contacts().size() << endl;
vector<Contact> vcnts(cnts.contacts().begin(), cnts.contacts().end());
for (auto &c : vcnts) {
cout << c.wxid() << "\t" << c.code() << "\t" << c.name() << "\t" << c.country() << "\t" << c.province() << "\t"
<< c.city() << "\t" << c.gender() << endl;
}
DbNames db = client.GetDbNames();
cout << "GetDbNames: " << db.names().size() << endl;
vector<string> dbs(db.names().begin(), db.names().end());
for (auto &name : dbs) {
cout << name << endl;
}
DbTables tbls = client.GetDbTables("db");
cout << "GetDbTables: " << tbls.tables().size() << endl;
vector<DbTable> vtbls(tbls.tables().begin(), tbls.tables().end());
for (auto &tbl : vtbls) {
cout << tbl.name() << "\n" << tbl.sql() << endl;
}
DbRows r = client.ExecDbQuery("MicroMsg.db", "SELECT * FROM Contact LIMIT 1;");
cout << "ExecDbQuery: " << r.rows().size() << endl;
vector<DbRow> vrows(r.rows().begin(), r.rows().end());
for (auto &row : vrows) {
vector<DbField> vfields(row.fields().begin(), row.fields().end());
for (auto &field : vfields)
cout << field.column() << "[" << field.type() << "]: " << field.content() << endl;
}
// 需要正确的 v3、v4 才能调用
// ret = client.AcceptNewFriend("v3", "v4");
// cout << "AcceptNewFriend: " << ret << endl;
function<void(WxMsg &)> cb = OnMsg;
thread t1 = thread([&]() { client.EnableRecvMsg(cb); });
// client.EnableRecvMsg(cb);
cout << "Block?..." << endl;
// gKeepRunning = true;
while (true) {
// cout << gKeepRunning << endl;
Sleep(1000);
}
Sleep(1000);
cout << "Exit..." << endl;
}