使用 /clr 或 clr:pure 编译时不支持互斥锁(cpprestsdk aka casablanca)
Mutex is not supported when compiling with /clr or clr:pure (cpprestsdk aka casablanca)
我用 64 bit
配置在 visual c++
中创建了一个 CLR project
,并尝试使用 cpprestsdk aka casablanca 64bit
.
但是我在运行项目的时候,出现了一个错误:
1>------ Build started: Project: Timestamp, Configuration: Debug x64 ------
1>MyForm.cpp
1>c:\program files (x86)\microsoft visual studio17\community\vc\tools\msvc.13.26128\include\mutex(8): fatal error C1189: #error: <mutex> is not supported when compiling with /clr or /clr:pure.
1>Testapi.cpp
1>c:\program files (x86)\microsoft visual studio17\community\vc\tools\msvc.13.26128\include\mutex(8): fatal error C1189: #error: <mutex> is not supported when compiling with /clr or /clr:pure.
1>Generating Code...
1>Done building project "Timestamp.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
其他错误:
E2093 a local lambda is not allowed in a member function of a managed class Timestamp c:\Users\Laptop-attendance\source\repos\Timestamp\Timestamp\Testapi.h 97
IDE 显示 .then
函数中 '['
个字符的错误,例如 .then([=](http_response response)
,如果您指出它,它会显示 "a local lambda is not allowed in a member function of a managed class"
如果我在具有 64 位配置的 Visual c++ Windows Console Application
中尝试 cpprestsdk
,它工作正常。
我正在使用 visual studio 2017.
您认为vc++的CLR项目中不能使用cpprestsdk吗?
谢谢。
这是我的代码,以及关于 cpprestsdk 的代码,我刚从它的教程中得到它:
#ifndef TESTAPI_H
#define TESTAPI_H
#pragma once
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <cpprest/json.h>
namespace Timestamp {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
using namespace utility; // Common utilities like string conversions
using namespace web; // Common features like URIs.
using namespace web::http; // Common HTTP functionality
using namespace web::http::client; // HTTP client features
using namespace concurrency::streams; // Asynchronous streams
/// <summary>
/// Summary for Testapi
/// </summary>
public ref class Testapi : public System::Windows::Forms::Form
{
public:
Testapi(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~Testapi()
{
if (components)
{
delete components;
}
}
private:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->SuspendLayout();
//
// Testapi
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(284, 261);
this->Name = L"Testapi";
this->Text = L"Testapi";
this->Load += gcnew System::EventHandler(this, &Testapi::Testapi_Load);
this->ResumeLayout(false);
}
#pragma endregion
private: System::Void Testapi_Load(System::Object^ sender, System::EventArgs^ e) {
auto fileStream = std::make_shared<ostream>();
// Open stream to output file.
pplx::task<void> requestTask = fstream::open_ostream(U("results.html")).then([=](ostream outFile)
{
*fileStream = outFile;
// Create http_client to send the request.
http_client client(U("http://13.231.231.252:3000/api/individual_employment_setting/detail/172"));
// Build request URI and start the request.
//uri_builder builder(U("/search"));
//builder.append_query(U("q"), U("cpprestsdk github"));
return client.request(methods::GET);
})
// Handle response headers arriving.
.then([=](http_response response)
{
printf("Received response status code:%u\n", response.status_code());
// Write response body into the file.
// return response.body().read_to_end(fileStream->streambuf());
stringstreambuf buffer;
response.body().read_to_end(buffer).get();
//show content in console
printf("Response body: \n %s", buffer.collection().c_str());
//parse content into a JSON object:
//json::value jsonvalue = json::value::parse(buffer.collection());
return fileStream->print(buffer.collection()); //write to file anyway
})
// Close the file stream.
.then([=](size_t)
{
return fileStream->close();
});
// Wait for all the outstanding I/O to complete and handle any exceptions
try
{
requestTask.wait();
}
catch (const std::exception &e)
{
printf("Error exception:%s\n", e.what());
}
}
};
}
#endif /*TESTAPI_H*/
您可以从 CLR 项目中调用使用互斥体的 class,您需要做的是创建一个普通的 c++ 项目并创建具有所需功能但不具备所需功能的 classes在它们的 headers 中公开 <mutex>
,然后您可以从您的 CLR 项目中自由调用这些 classes。
在 this answer 的最后,Hans Passant 给出了一个对您的情况很有用的提示。基本上,您需要一个单独的 c++ 库(关闭 clr 支持),在其中包装 cpprest
代码,link 这个库来自您的 CLR 项目,并确保没有包含的 header 会带来 <mutex>
英寸
举个例子,在 restwrapper.h header 文件中有一个这样的 class:
class RestWrapper
{
public:
void test();
};
在其实现文件中,restwrapper.cpp:
#include "restwrapper.h"
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <cpprest/json.h>
using namespace utility; // Common utilities like string conversions
using namespace web; // Common features like URIs.
using namespace web::http; // Common HTTP functionality
using namespace web::http::client; // HTTP client features
using namespace concurrency::streams; // Asynchronous streams
void RestWrapper::test()
{
auto fileStream = std::make_shared<ostream>();
// Open stream to output file.
pplx::task<void> requestTask = fstream::open_ostream(U("results.html")).then([=](ostream outFile)
{
*fileStream = outFile;
// Create http_client to send the request.
http_client client(U("http://13.231.231.252:3000/api/individual_employment_setting/detail/172"));
//etc ...
}
您可以在 DLL 中编译此 class(linking cpprest
及其所有相关库)然后使您的 CLR 项目 link 该库。在 CLR 项目中,您只需要包含 restwrapper.h,而这又不包含任何内容:
#include <restwrapper.h>
System::Void Testapi_Load(System::Object^ sender, System::EventArgs^ e)
{
RestWrapper wrapper;
wrapper.test();
}
只需右键单击您的 .cpp 文件,然后在 "General -> Common Language Runtime Support" select "No Common Language RunTime Support".
下
确实是最简单的解决方案。
我用 64 bit
配置在 visual c++
中创建了一个 CLR project
,并尝试使用 cpprestsdk aka casablanca 64bit
.
但是我在运行项目的时候,出现了一个错误:
1>------ Build started: Project: Timestamp, Configuration: Debug x64 ------
1>MyForm.cpp
1>c:\program files (x86)\microsoft visual studio17\community\vc\tools\msvc.13.26128\include\mutex(8): fatal error C1189: #error: <mutex> is not supported when compiling with /clr or /clr:pure.
1>Testapi.cpp
1>c:\program files (x86)\microsoft visual studio17\community\vc\tools\msvc.13.26128\include\mutex(8): fatal error C1189: #error: <mutex> is not supported when compiling with /clr or /clr:pure.
1>Generating Code...
1>Done building project "Timestamp.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
其他错误:
E2093 a local lambda is not allowed in a member function of a managed class Timestamp c:\Users\Laptop-attendance\source\repos\Timestamp\Timestamp\Testapi.h 97
IDE 显示 .then
函数中 '['
个字符的错误,例如 .then([=](http_response response)
,如果您指出它,它会显示 "a local lambda is not allowed in a member function of a managed class"
如果我在具有 64 位配置的 Visual c++ Windows Console Application
中尝试 cpprestsdk
,它工作正常。
我正在使用 visual studio 2017.
您认为vc++的CLR项目中不能使用cpprestsdk吗?
谢谢。
这是我的代码,以及关于 cpprestsdk 的代码,我刚从它的教程中得到它:
#ifndef TESTAPI_H
#define TESTAPI_H
#pragma once
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <cpprest/json.h>
namespace Timestamp {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
using namespace utility; // Common utilities like string conversions
using namespace web; // Common features like URIs.
using namespace web::http; // Common HTTP functionality
using namespace web::http::client; // HTTP client features
using namespace concurrency::streams; // Asynchronous streams
/// <summary>
/// Summary for Testapi
/// </summary>
public ref class Testapi : public System::Windows::Forms::Form
{
public:
Testapi(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~Testapi()
{
if (components)
{
delete components;
}
}
private:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->SuspendLayout();
//
// Testapi
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(284, 261);
this->Name = L"Testapi";
this->Text = L"Testapi";
this->Load += gcnew System::EventHandler(this, &Testapi::Testapi_Load);
this->ResumeLayout(false);
}
#pragma endregion
private: System::Void Testapi_Load(System::Object^ sender, System::EventArgs^ e) {
auto fileStream = std::make_shared<ostream>();
// Open stream to output file.
pplx::task<void> requestTask = fstream::open_ostream(U("results.html")).then([=](ostream outFile)
{
*fileStream = outFile;
// Create http_client to send the request.
http_client client(U("http://13.231.231.252:3000/api/individual_employment_setting/detail/172"));
// Build request URI and start the request.
//uri_builder builder(U("/search"));
//builder.append_query(U("q"), U("cpprestsdk github"));
return client.request(methods::GET);
})
// Handle response headers arriving.
.then([=](http_response response)
{
printf("Received response status code:%u\n", response.status_code());
// Write response body into the file.
// return response.body().read_to_end(fileStream->streambuf());
stringstreambuf buffer;
response.body().read_to_end(buffer).get();
//show content in console
printf("Response body: \n %s", buffer.collection().c_str());
//parse content into a JSON object:
//json::value jsonvalue = json::value::parse(buffer.collection());
return fileStream->print(buffer.collection()); //write to file anyway
})
// Close the file stream.
.then([=](size_t)
{
return fileStream->close();
});
// Wait for all the outstanding I/O to complete and handle any exceptions
try
{
requestTask.wait();
}
catch (const std::exception &e)
{
printf("Error exception:%s\n", e.what());
}
}
};
}
#endif /*TESTAPI_H*/
您可以从 CLR 项目中调用使用互斥体的 class,您需要做的是创建一个普通的 c++ 项目并创建具有所需功能但不具备所需功能的 classes在它们的 headers 中公开 <mutex>
,然后您可以从您的 CLR 项目中自由调用这些 classes。
在 this answer 的最后,Hans Passant 给出了一个对您的情况很有用的提示。基本上,您需要一个单独的 c++ 库(关闭 clr 支持),在其中包装 cpprest
代码,link 这个库来自您的 CLR 项目,并确保没有包含的 header 会带来 <mutex>
英寸
举个例子,在 restwrapper.h header 文件中有一个这样的 class:
class RestWrapper
{
public:
void test();
};
在其实现文件中,restwrapper.cpp:
#include "restwrapper.h"
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <cpprest/json.h>
using namespace utility; // Common utilities like string conversions
using namespace web; // Common features like URIs.
using namespace web::http; // Common HTTP functionality
using namespace web::http::client; // HTTP client features
using namespace concurrency::streams; // Asynchronous streams
void RestWrapper::test()
{
auto fileStream = std::make_shared<ostream>();
// Open stream to output file.
pplx::task<void> requestTask = fstream::open_ostream(U("results.html")).then([=](ostream outFile)
{
*fileStream = outFile;
// Create http_client to send the request.
http_client client(U("http://13.231.231.252:3000/api/individual_employment_setting/detail/172"));
//etc ...
}
您可以在 DLL 中编译此 class(linking cpprest
及其所有相关库)然后使您的 CLR 项目 link 该库。在 CLR 项目中,您只需要包含 restwrapper.h,而这又不包含任何内容:
#include <restwrapper.h>
System::Void Testapi_Load(System::Object^ sender, System::EventArgs^ e)
{
RestWrapper wrapper;
wrapper.test();
}
只需右键单击您的 .cpp 文件,然后在 "General -> Common Language Runtime Support" select "No Common Language RunTime Support".
下确实是最简单的解决方案。