如何从主函数为 dll (c++) 创建函数以在 c# 中使用
How to make function for dll (c++) from main function to use in c#
我需要在 C# 应用程序中使用我的 C++ 代码。我考虑过 pinvoke,但我对从我的 C++ 应用程序创建 dll 应该采用的方法感到困惑。
基本上,我的 c++ 应用程序是一个 main
函数,它运行无限循环的数据处理,我不知道如何将此类东西导出到 dll 并从 c# 调用它。
我试图在 dll 的独立 init
函数中重写我的 main
函数并从 c# 调用它,但因为它是一个无限循环,所以它从未达到 return
的地步从功能。而且我不知道如何在某些时候将我的数据缓冲区从无限循环获取到我的 c# 应用程序。
我目前所做的:
// myDLL.cpp
int __stdcall OpenRTSP(char url, char progname)
{
TaskScheduler* scheduler = BasicTaskScheduler::createNew();
UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler);
if (openURL(*env, &progname, &url) < 0)
{
return -1;
}
// All subsequent activity takes place within the event loop:
// This function call does not return, unless programm closes.
env->taskScheduler().doEventLoop(&eventLoopWatchVariable);
return 0;
}
// myDLL.h
__declspec(dllexport) int __stdcall OpenRTSP(char url, char progname);
我不知道如何从 c# 调用 OpenRTSP,因为它永远不会 return 从这个 func 以及如何编写一个函数,它将 return 我从无限循环中获取数据缓冲区?
如果您需要的功能确实是 main()
并且您不需要与 C# 应用程序交互,您可以 运行 您的可执行文件作为外部进程。查看 System.Diagnostics.Process
如何执行此操作的文档。
如果这不是您的正确选择,请尝试通过 P/Invoke 从单独的线程调用您的阻塞函数。
因为你的 C++ 程序 运行 是一个连续的过程,你最好让它成为一个独立的过程,并且 运行 从你的 C# 代码中使用 Process
class. The data from you C++ process can be passed by virtue of some IPC methods. The simple STDOUT seems to fit your task quite well. This post 描述它如何实现了。
这是一个简短的代码示例:
var cppProcess = new Process();
cppProcess.StartInfo = new ProcessStartInfo
{
FileName = "YourCppApp.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
};
cppProcess.OutputDataReceived += (sender, arg) =>
{
Console.WriteLine("Received: {0}", arg.Data);
};
cppProcess.Start();
cppProcess.BeginOutputReadLine();
如果您从 C++ 应用程序发回的缓冲区应该是二进制的,请使用 BinaryReader
从 C++ 应用程序的 STDOUT 读取:
var cppProcess = new Process();
cppProcess.StartInfo = new ProcessStartInfo
{
FileName = "YourCppApp.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
};
cppProcess.Start();
using (var cppOutput = new BinaryReader(cppProcess.StandardOutput.BaseStream))
while (!cppProcess.StandardOutput.EndOfStream)
{
var buffer = new byte[4096];
int bytesRead= cppOutput.Read(buffer, 0, buffer.Length);
// Process the buffer...
}
或者,您可以将 main
函数更改为您已经尝试过的库函数,并将 C# 中的回调函数作为参数传递给它。但这会更乏味,我个人不会在您的特定情况下这样做。
创建一个 CLR 项目并将其导入 c#,如果您有完整的 c++ 代码,那将不是问题。
只需:新建项目->C++->CLR->Class 库。
然后在 header 你写这样的东西:
// filename.h
#pragma once
using namespace System;
namespace YourNampespace
{
public ref class YourClass abstract sealed
{
//int __stdcall OpenRTSP(char url, char progname);
//You want to convert this to managed, buf if you return "int", with "char" params,
// it won't be a problem
}
}
然后在源文件上:
#include "stdafx.h"
#include "filename.h"
int YourNampespace::YourClass::__stdcall OpenRTSP(char url, char progname)
{
//Code here
}
我几乎不懂任何 C++,我不确定 "endless loop of data processing" 是什么意思,但是您可以将 "sent" 的数据写入流,return 它到 c# 应用程序并从那里读取它。没有进程间的东西(我认为那会带来更多问题)
我需要在 C# 应用程序中使用我的 C++ 代码。我考虑过 pinvoke,但我对从我的 C++ 应用程序创建 dll 应该采用的方法感到困惑。
基本上,我的 c++ 应用程序是一个 main
函数,它运行无限循环的数据处理,我不知道如何将此类东西导出到 dll 并从 c# 调用它。
我试图在 dll 的独立 init
函数中重写我的 main
函数并从 c# 调用它,但因为它是一个无限循环,所以它从未达到 return
的地步从功能。而且我不知道如何在某些时候将我的数据缓冲区从无限循环获取到我的 c# 应用程序。
我目前所做的:
// myDLL.cpp
int __stdcall OpenRTSP(char url, char progname)
{
TaskScheduler* scheduler = BasicTaskScheduler::createNew();
UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler);
if (openURL(*env, &progname, &url) < 0)
{
return -1;
}
// All subsequent activity takes place within the event loop:
// This function call does not return, unless programm closes.
env->taskScheduler().doEventLoop(&eventLoopWatchVariable);
return 0;
}
// myDLL.h
__declspec(dllexport) int __stdcall OpenRTSP(char url, char progname);
我不知道如何从 c# 调用 OpenRTSP,因为它永远不会 return 从这个 func 以及如何编写一个函数,它将 return 我从无限循环中获取数据缓冲区?
如果您需要的功能确实是 main()
并且您不需要与 C# 应用程序交互,您可以 运行 您的可执行文件作为外部进程。查看 System.Diagnostics.Process
如何执行此操作的文档。
如果这不是您的正确选择,请尝试通过 P/Invoke 从单独的线程调用您的阻塞函数。
因为你的 C++ 程序 运行 是一个连续的过程,你最好让它成为一个独立的过程,并且 运行 从你的 C# 代码中使用 Process
class. The data from you C++ process can be passed by virtue of some IPC methods. The simple STDOUT seems to fit your task quite well. This post 描述它如何实现了。
这是一个简短的代码示例:
var cppProcess = new Process();
cppProcess.StartInfo = new ProcessStartInfo
{
FileName = "YourCppApp.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
};
cppProcess.OutputDataReceived += (sender, arg) =>
{
Console.WriteLine("Received: {0}", arg.Data);
};
cppProcess.Start();
cppProcess.BeginOutputReadLine();
如果您从 C++ 应用程序发回的缓冲区应该是二进制的,请使用 BinaryReader
从 C++ 应用程序的 STDOUT 读取:
var cppProcess = new Process();
cppProcess.StartInfo = new ProcessStartInfo
{
FileName = "YourCppApp.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
};
cppProcess.Start();
using (var cppOutput = new BinaryReader(cppProcess.StandardOutput.BaseStream))
while (!cppProcess.StandardOutput.EndOfStream)
{
var buffer = new byte[4096];
int bytesRead= cppOutput.Read(buffer, 0, buffer.Length);
// Process the buffer...
}
或者,您可以将 main
函数更改为您已经尝试过的库函数,并将 C# 中的回调函数作为参数传递给它。但这会更乏味,我个人不会在您的特定情况下这样做。
创建一个 CLR 项目并将其导入 c#,如果您有完整的 c++ 代码,那将不是问题。
只需:新建项目->C++->CLR->Class 库。 然后在 header 你写这样的东西:
// filename.h
#pragma once
using namespace System;
namespace YourNampespace
{
public ref class YourClass abstract sealed
{
//int __stdcall OpenRTSP(char url, char progname);
//You want to convert this to managed, buf if you return "int", with "char" params,
// it won't be a problem
}
}
然后在源文件上:
#include "stdafx.h"
#include "filename.h"
int YourNampespace::YourClass::__stdcall OpenRTSP(char url, char progname)
{
//Code here
}
我几乎不懂任何 C++,我不确定 "endless loop of data processing" 是什么意思,但是您可以将 "sent" 的数据写入流,return 它到 c# 应用程序并从那里读取它。没有进程间的东西(我认为那会带来更多问题)