如何从c#中使用的主函数中生成dll(c++)的函数

本文关键字:函数 dll c++ | 更新日期: 2023-09-27 18:00:09

我需要在c#应用程序中使用我的c++代码。我想过pinvoke,但我对从我的c++应用程序创建dll的方法感到困惑。基本上,我的c++应用程序是一个main函数,它运行着一个无休止的数据处理循环,我不知道如何将这样的东西导出到dll并从c#调用它。

我试图在dll的独立init函数中重写我的main函数,并从c#调用它,但因为这是一个无休止的循环,所以它从未达到使用return from函数的目的。我不知道如何在某个时刻将我的数据缓冲区从无休止的循环中获取到我的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,因为它永远不会从这个函数返回,以及如何编写一个函数,它会从无尽的循环中返回一个数据缓冲区?

如何从c#中使用的主函数中生成dll(c++)的函数

由于您的C++程序运行一个连续的进程,您可能最好将其保留为一个独立的进程,并使用Process类从C#代码中运行它。C++进程中的数据可以通过一些IPC方法传递。简单的STDOUT似乎非常适合您的任务。这篇文章描述了如何实现这一目标。

下面是一个简短的代码示例:

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#中的回调函数作为参数传递给它。但这会更乏味,我个人不会在你的特殊情况下这样做。

如果您需要的函数确实是main(),并且您不需要与C#应用程序交互,那么您可以将可执行文件作为外部进程运行。查看System.Diagnostics.Process的文档中如何做到这一点。

如果这不是适合您的选项,请尝试从单独的线程通过p/Invoke调用您的阻塞函数。

创建一个CLR项目并将其导入c#,如果您有完整的c++代码,那就不会有问题。

只需:新建项目->C++->CLR->类库。然后在标题上写下这样的内容:

// 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++,我也不确定你所说的"无休止的数据处理循环"是什么意思,但你可以把哪些数据"发送"到流中,返回到c#应用程序,然后从那里读取。没有进程间的事情(我认为这会带来更多问题)