C++控制台应用程序调用C++/CLI静态库

C++ console app call C++/CLI static library

本文关键字:C++ 静态 CLI 调用 控制台 应用程序      更新时间:2023-10-16

我正在考虑创建一个C++/CLI静态库的想法,该库为托管EventLogger功能公开了许多静态函数。我当前的解决方案存在于/clr编译的C++项目和C++控制台应用程序之外。

Visual Studio告诉我ConsoleApp需要使用/clr参数进行编译,但这是我不想做的事情。有什么方法可以实现我在这里要做的吗?

#### ConsoleApp.cpp
#include <iostream>
#include "../ClrEtwLogger/ClrEtwLogger.h"
int main()
{
clr_etw_logger::etw_logger::etw_log();
}
#### ClrEtwLogger.h (/clr), static library
#pragma once
#using <system.dll>
using namespace System;
using namespace Diagnostics;
namespace clr_etw_logger
{
public ref class etw_logger
{
public:
static void etw_log()
{
const auto source = gcnew String("dotNet ClrEtwLogger");
const auto log = gcnew String("EtwLogger");
const auto event = gcnew String("Sample Event 1");
if (!EventLog::SourceExists(source))
{
EventLog::CreateEventSource(source, log);
}
EventLog::WriteEntry(source, event);
EventLog::WriteEntry(source, event, EventLogEntryType::Warning, 234);
}
};
}

是的,您可以将托管代码封装在非托管函数中,并按照以下步骤从托管项目中调用它,

1>创建一个空项目c++项目

2>配置->中将公共语言运行时支持设置为公共语言运行时间支持(/clr(高级页面

3>配置中>C++>命令行,添加此文本以清除链接器错误->/Zc:to-

4>将.NET版本设置为您在配置->中安装的版本.NET Framework版本字段中的高级页面,例如4.8

5>添加对必要的Dlls 的引用

在我的例子中,我引用了以下程序集

System
System.Data
System.Windows.Forms
System.Drawing

6>配置->常规页面,将配置类型更改为静态库,

7>配置->高级页面,将目标文件扩展名更改为.lib在本例中,代码在main.cpp中编译,没有头文件

using namespace System;
using namespace System::Threading;
using namespace System::Windows::Forms;
using namespace System::Windows;
namespace MyApp
{
public ref class MyForm : public Form
{
public:
MyForm() {
InitializeComponent();
}
ProgressBar^ GetProgressBar() {
return pgb;
}
protected:
~MyForm() {
}
private:
ProgressBar^ pgb;
void InitializeComponent() {
pgb = gcnew ProgressBar();
SuspendLayout();
// 
// progressBar
// 
pgb->Dock = DockStyle::Fill;
pgb->Location = Drawing::Point(0, 0);
pgb->Name = "pgb";
pgb->Size = Drawing::Size(200, 20);
pgb->TabIndex = 0;
// 
// MyForm
// 
ClientSize = Drawing::Size(200, 20);
Controls->Add(pgb);
auto fs = Forms::FormBorderStyle::FixedSingle;
this->FormBorderStyle = fs;
MaximizeBox = false;
MinimizeBox = false;
Name = "MyForm";
auto sp = FormStartPosition::CenterScreen;
StartPosition = sp;
Text = "My Form";
ResumeLayout(false);
}
};
}
void ShowProgress() {
auto f = gcnew MyApp::MyForm();
f->TopMost = true;
f->Show();
f->GetProgressBar()->Visible = true;
f->GetProgressBar()->Minimum = 1;
f->GetProgressBar()->Maximum = 100;
f->GetProgressBar()->Value = 90;
f->GetProgressBar()->Step = 1;
auto fv = f->GetProgressBar()->Value;
while (fv < 10)
{
f->GetProgressBar()->Value += 1;
Thread::Sleep(1);
f->Update();
}
f->Close();
}
void RunProgress() {
try {
auto ts = gcnew ThreadStart(ShowProgress);
auto t = gcnew Thread(ts);
t->SetApartmentState(ApartmentState::STA);
t->Start();
t->Join();
}
catch (Exception^ e) {
// TODO: Handle any exceptions
}
}
void ShowProgressBar()
{
MyApp::MyForm^ form = nullptr;
form = gcnew  MyApp::MyForm();
form->TopMost = true;
form->Show();
form->GetProgressBar()->Visible = true;
form->GetProgressBar()->Minimum = 1;
form->GetProgressBar()->Maximum = 100;
form->GetProgressBar()->Value = 1;
form->GetProgressBar()->Step = 1;
auto i = 0;
if (form)
{
while (form->GetProgressBar()->Value < 100)
{
form->GetProgressBar()->Value += 1;
form->Update();
Thread::Sleep(1);
}
form->Close();
}
}
//this is the function to be exported
extern "C" void RunProgressBar()
{
try
{
Thread^ progressBarThread = gcnew Thread(gcnew ThreadStart(ShowProgressBar));
progressBarThread->SetApartmentState(ApartmentState::STA);
progressBarThread->Start();
progressBarThread->Join();
}
catch (System::Exception^ e)
{
// Your main application code here

}
}

然后您可以从非托管项目中调用代码通过引用库并定义导入的函数,如

#pragma comment(lib, "RunProgressBarLib.lib") 
// Creates a progress bar for 
//a short amount of time
extern "C" void RunProgressBar();

您可以使用的c++版本有一些限制,c++17可能与clr、不兼容

在.NET级别处理异常也很重要,以免它们导致非托管代码崩溃。