Aleksey
Aleksey

Reputation: 115

How to make function for dll (c++) from main function to use in c#

I need to use my c++ code in c# application. I thought about pinvoke, but I'm confused with the approach I should take for creating dll from my c++ app. Basically, my c++ app is a main function, which runs an endless loop of data processing and I dont know how I can export such thing to dll and call it from c#.

I tried to rewrite my main function in standalone init function for dll and call it from c#, but because its a endless loop it never came to the point with return from function. And I dont know how to get my data buffer from endless loop at some point to my c# app.

What I've done currently:

// 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);

I dont know how to call OpenRTSP from c#, because it will never return from this func and how to write a function, which will return me a data buffer from endless loop?

Upvotes: 1

Views: 465

Answers (3)

Dmitry Egorov
Dmitry Egorov

Reputation: 9650

Since your C++ program runs a continuous process, you'd probably better leave it a standalone process and run it from your C# code using 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 describes how it can be achieved.

Here's a brief code sample:

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();

If the buffer you send back from the C++ app should rather be binary, use BinaryReader to read from the C++ app's 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...
    }

Alternatively, you may change your main function to a library function as you have already tried to do and pass it a callback function from C# as a parameters. But this would be more tedious and I personally would not go for this in your particular case.

Upvotes: 2

Pau C
Pau C

Reputation: 783

Create a CLR project and import it to c#, if you have the full c++ code it won't be a problem.

To do it just: New Project->C++->CLR->Class library. Then on the header you write something like this:

// 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
  }
}

Then on the source file:

#include "stdafx.h"
#include "filename.h"
int YourNampespace::YourClass::__stdcall OpenRTSP(char url, char progname)
{
 //Code here
}

I almost don't know any c++ and I'm not sure what do you mean by "endless loop of data processing"¨, but you could write the which data is "sent" to a stream, return it to the c# app and read it from there. No interprocess things (I think that would bring more problems)

Upvotes: 0

candidus
candidus

Reputation: 129

If the function you need is indeed main() and you don't need to interact with your C# application you can run your executable as an external process. Look at the documentation of System.Diagnostics.Process how to do that.

If this is not the right option for you then try to call your blocking function via P/Invoke from a separate thread.

Upvotes: 0

Related Questions