I'm writing a C# application that calls a C++ dll. This dll is a device driver for an imaging system; when the image is being acquired, a preview of the image is available from the library on a line-by-line basis. The C++ dll takes a callback to fill in the preview, and that callback consists basically of the size of the final image, the currently scanned line, and the line of data itself.
Problem is, there's a pretty serious delay from the time when scanning stops and the C# callback stops getting information. The flow of the program goes something like:
Assign callback to C++ dll from within C#
User starts to get data
Device starts up
dll starts to call the callback after a few seconds (normal)
Device finishes image formation
dll is still calling the callback for double the time of image formation.
This same dll worked with a C++ application just fine; there does not appear to be that last step delay. In C#, however, if I have the callback immediately return, the delay still exists; no matter what I do inside the callback, it's there.
Is this delay an inherent limitation of calling managed code from unmanaged code, or is there something either side could do to make this go faster? I am in contact with the C++ library writer, so it's possible to implement a fix from the C++ side.
Edit: Could doing something simple like a named pipe work? Could an application read from its own pipe?
It may be possible that the Managed Debug Assistant that checks native callbacks for garbage collected targets may be the culprit (is it in debug mode under the debugger?)
See the PSA: Pinvokes may be 100x slower under the debugger blog entry by Mike Stall.
Are you doing any funky data marshalling across the interop layer? If so then you may have a huge delay whilst it's basically marshalling all your image data by converting it. You can easily test this as the large the image data, the longer it will take
A few possible alternatives that spring to mind are
1.Use a memory mapped file though you'd need to implement a simple semaphore or signalling system to say 'I have data ready' and 'I have consumed the data
2. Compile the C++ dll in mixed mode ( any C++ code can be compiled into .NET with the /clr flag ) then use C#/CLI
3. Use Remoting and IPC Channels - maybe a bit of an overkill but worth a look
Hope that helps
Turns out the delay is in the C++ side, by a developer who swore up and down it wasn't.
Related
I built a C# WPF (.NET Core 3.1) application using that has got some interest and I'm about to monetize it.
However, building any kind of license check in C# is pretty much useless, and any user would be able to use a decompiler such as ILSpy to crack it, thus rendering my work pretty much useless.
I took a long hard look on the .NET obfuscators, but ultimately concluded they did not fit my requirements because there are decompilers that can still retrieve the code from Dotfuscator, Babel, Obfuscar, etc. Simply obfuscating names and whatnot isn't really useful, as one could simple debug the code to the point where a license is required.
What I'm trying to do now is build a C/C++ launcher that will execute my .NET from memory.
My plan is to stream the bytes from a server, load them in memory, and run the program. I, however, don't know a whole lot about how I could achieve this.
I've tried VirtualAlloc to allocate all the bytes and changed set memory page to be executable, but it didn't work.
I've tried adjustments based on a few pieces of code that run PE from memory:
https://github.com/aaaddress1/RunPE-In-Memory
https://github.com/codecrack3/Run-PE---Run-Portable-Executable-From-Memory/blob/master/RunPE.cpp
https://www.codeproject.com/Articles/13897/Load-an-EXE-File-and-Run-It-from-Memory
The closes I got was a 0xc0000005 error when trying to run the executable from memory (an array of bytes that makeup my program).
How can this be done? I'd really like to avoid having to rewrite the whole thing in C/C++, specially because of the complex UI.
I have a C# application that does a few bits and pieces, but the main task it performs is done by a Delphi DLL which it calls.
This Delphi DLL is a total memory hog, which needs to cache a lot of DB-information locally for speed. I'm happy that it's not leaky, as FastMM4 isn't reporting any memory leaks when the code is run within Delphi.
I am starting to run into problems, however, when the control is returned to C#. The C# code attempts to do some calculations on the results of the Delphi app (all results marshalled via a DB). These calculations usually involve a million or so doubles so not extreme memory usage, however the code keeps returning me out of memory exceptions.
I assume that FastMM4 in the Delphi code still hasn't returned the freed memory to Windows (and hence available to the C# code), so the process is still using it's maximum 32-bit memory allocation and C# can't obtain more when it needs to.
So, how do I get the memory used (and freed) by Delphi usable again by the C# code? I thought we may want to do one of the following:
Force an unload of the Delphi DLL from the C# side (my colleague doesn't think this will work, as he thinks it'll just unload the code rather than the memory used on the heap) - probably LoadLibrary/FreeLibrary?
Make a call at the end of the Delphi DLL to release the memory back to Windows (I tried SetWorkingProcessSetSize before, but didn't seem to do anything, should I use a different call?)
Wrap the Delphi DLL in a C# DLL and call it in a different AppDomain (I don't like this from a style perspective as we're creating wrappers just to hold wrappers.
Anything else I've missed?
Force an unload of the Delphi DLL from the C# side (my colleague doesn't think this will work, as he thinks it'll just unload the code rather than the memory used on the heap) - probably LoadLibrary/FreeLibrary?
This will just work. When the DLL unloads, FastMM will finalize and return the memory that it reserved and committed.
One thing I would do is make a call to GC.Collect before calling your library. .NET knows what to do when more managed memory is requested than can fit and calls the collector automatically, however it has no clue what you're doing in native code so there will be a lot of memory allocated needlessly.
I would also move from a 32 bit architecture. It's not that you ran out of memory, it's that you ran out of consecutive memory large enough to fit whatever you're trying to do in Delphi. A larger virtual address space will fix that issue for you, and there hasn't been a processor made in the past 6 years that didn't wasn't 64 bit capable. It's time to take those shy steps into the bright future ahead of us.
I have a C# application that uses an unmanaged C++ DLL. I've found a crash that only happens in WinXP (not Win7) when the memory I'm passing back from the C++ DLL is too big.
The basic flow is that C# starts an operation in the C++ DLL by calling a start function, in which it provides a callback. The C++ DLL then performs the operation and dumps logging information into a text buffer. When the operation is completed the C++ DLL calls the callback and passes the text buffer as a parameter:
C++:
typedef void (CALLBACK *onfilecallbackfunc_t)(LPCWSTR);
DLL_API void NWAperture_SetOnFileCallback(onfilecallbackfunc_t p_pCallback);
l_pFileCallback(_wstringCapture.c_str());
C#:
public delegate void FileCallback([MarshalAs(UnmanagedType.LPWStr)] string buffer);
public static extern void SetOnFileCallback(FileCallback fileCallback);
private void OnFile(string buffer);
This works fine in Win7, but in WinXP if the buffer gets too big it crashes. I'm not sure of the exact size that causes this but I've put an 8MB limit on it and the crash has disappeared.
Does anyone know of a limit on the amount of memory that can be transferred between C++ and C# like this in WinXP? Or have I completely misunderstood this problem and there's a more logical explanation?
Update: I should have been more specific - this occurs on the same PC with WinXP and Win7 dual boot, both 32-bit OS.
So it eventually turned out I was being an idiot. In order to make the log large but speed the testing up I was clicking on the cancel button, which called a function in the C++ DLL that stopped execution and called the callback function with an 'abort' error and whatever log had already been recorded. But when I did this the execution didn't stop immediately, so when the callback with the log was in progress the C++ code could attempt to add to the log. This caused the instability I was seeing.
I fixed it by using a critical section around the log.
You can run out of contiguous memory way before you actually run out of RAM. This is the one big down side of using Array buffers. LinkedLists (or arrays using chunking) help mitigate this issue, because the space you need doesn't have to be contiguous.
So unless your application is using 2+ GB of RAM, than your issue is more likely memory fragmentation than anything else.
Windows 7 is probably managing the RAM differently than Windows XP, that's probably why you're not seeing the problem there. But push more data through and I'm sure you'll run into the same issue there.
You can setup perfmon to track/log memory usage of your system and task manager to track your application.
I'm not aware of any hard limit set by Windows or NETFX, but I am highly suspicious that the volume of data returned from your C++ app could be entirely arbitrary and this could result in volatile behavior.
I strongly recommend considering writing your log data to a file in your native component and then reading the file from your managed code. This way, it doesn't matter how much data is logged, your managed code can parse through it without worrying about blowing its heap.
I have a project in which I'll have to process 100s if not 1000s of messages a second, and process/plot this data on graphs accordingly. (The user will search for a set of data in which the graph will be plotted in real time, not literally having to plot 1000s of values on a graph.)
I'm having trouble understanding using DLLs for having the bulk of the message processing in C++, but then handing the information into a C# interface. Can someone dumb it down for me here?
Also, as speed will be a priority, I was wondering if accessing across 2 different layers of code will have more of a performance hit than programming the project in its entirety in C#, or of course, C++. However, I've read bad things about programming a GUI in C++; in regards to which, this application must also look modern, clean, professional etc. So I was thinking C# would be the way forward (perhaps XAML, WPF).
Thanks for your time.
The simplest way to interop between a C/C++ DLL and a .NET Assembly is through p/invoke. On the C/C++ side, create a DLL as you would any other. On the C# side you create a p/invoke declaration. For example, say your DLL is mydll.dll and it exports a method void Foo():
[DllImport("mydll.dll")]
extern static void Foo();
That's it. You simply call Foo like any other static class method. The hard part is getting data marshalled and that is a complicated subject. If you are writing the DLL you can probably go out of your way to make the export functions easily marshalled. For more on the topic of p/invoke marshalling see here: http://msdn.microsoft.com/en-us/magazine/cc164123.aspx.
You will take a performance hit when using p/invoke. Every time a managed application makes an unmanaged method call, it takes a hit crossing the managed/unmanaged boundary and then back again. When you marshal data, a lot of copying goes on. The copying can be reduced if necessary by using 'unsafe' C# code (using pointers to access unmanaged memory directly).
What you should be aware of is that all .NET applications are chock full of p/invoke calls. No .NET application can avoid making Operating System calls and every OS call has to cross into the unmanaged world of the OS. WinForms and even WPF GUI applications make that journey many hundreds, even thousands of times a second.
If it were my task, I would first do it 100% in C#. I would then profile it and tweak performance as necessary.
If speed is your priority, C++ might be the better choice. Try to make some estimations about how hard the calculation really is (1000 messages can be trivial to handle in C# if the calculation per message is easy, and they can be too hard for even the best optimized program). C++ might have some more advantages (regarding performance) over C# if your algorithms are complex, involving different classes, etc.
You might want to take a look at this question for a performance comparison.
Separating back-end and front-end is a good idea. Whether you get a performance penalty from having one in C++ and the other in C# depends on how much data conversion is actually necessary.
I don't think programming the GUI is a pain in general. MFC might be painful, Qt is not (IMHO).
Maybe this gives you some points to start with!
Another possible way to go: sounds like this task is a prime target for parallelization. Build your app in such a way that it can split its workload on several CPU cores or even different machines. Then you can solve your performance problems (if there will be any) by throwing hardware at them.
If you have C/C++ source, consider linking it into C++/CLI .NET Assembly. This kind of project allows you to mix unmanaged code and put managed interfaces on it. The result is a simple .NET assembly which is trivial to use in C# or VB.NET projects.
There is built-in marshaling of simple types, so that you can call functions from the managed C++ side into the unmanaged side.
The only thing you need to be aware of is that when you marshal a delegate into a function pointer, it doesn't hold a reference, so if you need the C++ to hold managed callbacks, you need to arrange for a reference to be held. Other than that, most of the built-in conversions work as expected. Visual Studio will even let you debug across the boundary (turn on unmanaged debugging).
If you have a .lib, you can use it in a C++/CLI project as long as it's linked to the C-Runtime dynamically.
You should really prototype this in C# before you start screwing around with marshalling and unmarshalling data into unsafe structures so that you can invoke functions in a C++ DLL. C# is very often faster than you think it'll be. Prototyping is cheap.
I have an unmanaged C++ exe that I could call from inside my C# code directly (have the C++ code that I could make a lib) or via spawning a process and grabbing the data from the OutputStream. What are the advantages/disadvantages of the options?
Since you have source code of the C++ library, you can use C++/CLI to compile it into a mixed mode dll so it is easy to be used by the C# application.
The benefit of this will be most flexible on data flow (input or output to that C++ module).
While running the C++ code out of process has one benefit. If your C++ code is not very robust, this can make your main C# process stable so as not to be crashed by the C++ code.
The big downside to scraping the OutputStream is the lack of data typing. I'd much rather do the work of exporting a few functions and reusing an existing library; but, that's really just a preference.
Another disadvantage of spawning a process is that on windows spwaning a process is a very expensive (slow) operation. If you intend to call the c++ code quite often this is worth considering.
An advantage can be that you're automatically more isolated to crashes in the c++ program.
Drop in replacement of the c++ executable can be an advantage as well.
Furthermore writing interop code can be big hassle in c#. If it's a complicated interace and you decide to do interop, have a look at c++/cli for the interop layer.
You're far better off taking a subset of the functions of the C++ executable and building it into a library. You'll keep type safety and you'll be able to better leverage Exception Handling (not to mention finer grain control of how you manage the calls into the functions in the library).
If you go with grabbing the data from the OutputStream of the executable, you're going to have no visibility into the processes of the executable, no real exception handling, and you're going to lose any type information you may have had.
The main disadvantage to being in process would be making sure you handle the managed/native interactions correctly.
1)
The c++ code will probably depend on deterministic destruction for cleanup/resource freeing etc. I say probably because this is common and good practice in c++.
In the managed code this means you have to be careful to dispose of your c++ cli wrapper code properly. If your code is used once, a using clause in c# will do this for you. If the object needs to live a while as a member you'll find that the dispose will need to be chained the whole way through your application.
2)
Another issue depends on how memory hungry your application is. The managed garbage collector can be lazy. It is guaranteed to kick in if a managed allocation needs more space than is available. However the unmanaged allocator is not connected in anyway. Therefore you need to manaully inform the managed allocator that you will be making unmanaged allocations and that it should keep that space available. This is done using the AddMemoryPressure method.
The main disadvantages to being out of process are:
1) Speed.
2) Code overhead to manage the communication.
3) Code overhead to watch for one or other process dying when it is not expected to.