I have managed web application (WCF service running from IIS, FWIW) written in c#. In certain situations, it performs calls to functions from unmanaged c/c++ library.
Inside the unmanaged library I have some global static variable.
I see that some of the times the value of this variable changes to its initial value between the calls while I would expect it to keep its value always.
The structure is something like this:
Managed.cs
public class Managed
{
[DllImport("native.dll", EntryPoint = "?MyFunc##YGXXZ", ExactSpelling = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
static extern void MyFunc();
public void MyWrapper()
{
MyFunc();
}
}
}
Native.cpp
static int counter = -1;
__declspec(dllexport) void __stdcall MyFunc()
{
counter++; // sometimes when I enter this function the counter drops to -1
}
My question is: Does it work as supposed to? Am I missing something? How can I "remember" the value of the variable between the calls?
EDIT: Actually I have 2 web applications running in the same application pool in IIS. So it looks like these 2 applications while running in the same IIS working process, each one loads different instance of my DLL. So the static variables in these two instances are unrelated. Now my (updated) question is: how can I make these 2 applications share the instance of native DLL? And also - how can it be that the same worker process has 2 copies of DLL loaded simultaneously?
After some research I found that the problem was with multiple web applications running from the same application pool. Though IIS uses the same working process for all of the applications, it looks like somehow it creates different copies of unmanaged dlls for each application with different handles and different sets of static variables. That's why they were re-initialized.
Related
I am calling some unmanaged C functions (in an external dll) from C#. I have 2 different methods to do so, and I am not sure of the differences between the 2 (other than the amount of code)
Method #1
[DllImport("PComm32.dll",CallingConvention=CallingConvention.StdCall, EntryPoint ="PmacSelect")]
public static extern int PmacSelect(IntPtr intPtr);
int device = PmacSelect(IntPrt.Zero);
Method #2
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate int PmacSelect(IntPrt intptr);
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);
public PmacSelect PmacSelectFunction;
private IntPtr pDll = LoadLibrary("PComm32");
IntPtr pAddressOfFunctionToCall = GetProcAddress(pDll, "PmacSelect"); //find the function in the loaded pcomm32 dll
PmacSelectFunction = (PmacSelect)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall,type(PmacSelect));
int device = PmacSelectFunction(IntPrt.Zero);
Both methods work, and call the PmacSelect Function located in the PComm32.dll file.
My question is what are the functional differences between the 2 methods?
Method #1 must rely on windows managing the DLL in the background for me as needed? Could windows load and unload the dll without my knowledge? I dont really care if it does, as long as it automatically loads is when I call a function in the dll.
Method #2 The DLL is loaded explicitly when I call LoadLibrary. Does the library remain in memory until I free it?
I'll give you answers, but you seem to already understand what is going on.
My question is what are the functional differences between the 2 methods?
There is no functional difference between the two methods. In the first method (which you should use if at all possible), the DotNet framework is handling everything for you. Under the hood, it is doing exactly what you're doing manually: Calling LoadLibrary, GetProcAddress, and at some point, FreeLibrary. Those are the steps to calling a function in a DLL.
Method #1 must rely on windows managing the DLL in the background for me as needed? Could windows load and unload the dll without my knowledge?
Yes, that's exactly right, although I wouldn't say it is without your knowledge. You are telling it to do that when you write [DllImport("PComm32.dll"...)].
Method #2 The DLL is loaded explicitly when I call LoadLibrary. Does the library remain in memory until I free it?
Again, yes, you understand what is happening.
Since you seem to answered your own questions and I've merely confirmed your answers, let you give you the reasons why you should (almost) always use #1:
It works just as well
It is easier to use and easier to read / maintain
There is no value in doing it the hard way (#2)
I can only think of one reason that you would ever want to bother with the second method: If you needed to be able to replace the DLL, on the fly, with a newer version or something, without quitting your application, then you would want the fine grain control over when the DLL is unloaded (so that the file can be replaced).
That is unlikely to be a requirement except in very special cases.
Bottom Line: If you're using C#, you accept the fact that you are giving control to the framework in exchange for being able to focus on the work, and not worry about things like DLL or memory management. The DotNet framework is your friend, let it do the heavy lifting for you, and focus your efforts on the rest of the code.
When you pinvoke with DllImport, LoadLibrary ends up getting called for you, and the exported function is (hopefully) found in the EAT. Basically in your second example you're doing the same thing as a typedef + GetModuleHandle & GetProcAddress for c/c++.
The only reason I could think to use your second method, would be if the DllMain of your unmanaged module executes code upon attachment to a process, which you might depending on the scenario want to have specific timing control over when that module gets loaded into your process.
A pointer is passed to me from a C++ dll as followed:
[DllImport("myfile.dll", EntryPoint = "LoadFile", SetLastError = true, CharSet = CharSet.None)]
public static extern IntPtr dLoadFile(string x);
IntPtr p = dLoadFile("myfile");
//Do things with p.
Marshal.FreeHGlobal(p) //crash on this line with exception below.
System.Runtime.InteropServices.COMException: 'One or more arguments
are invalid (Exception from HRESULT: 0x80000003)'
Should I free the memory allocated to IntPtr ? And if yes, how to do it properly ?
Obviously it seems that Marshal.FreeHGlobal() is not the way to go...
Thanks
The general rule is that "who allocates the resources needs to be called to perform the cleanup". In c#, you d not own the memory : the clr owns it. Your shared c# assemblies also share the clr, therfore you have the impression to create an object in one assembly and free it in another. When performing interoperability, a resource created by a library should be cleaned up by the same library via an additional exported api. There are some exceptions though, and they regard when operating systems objects are created :according to the specific documentation of the object in question, you can free the resource at caller site.
In your case, you should export the appropriate api in my file.dll that properly perform the cleanup.
This rule allows you not to disclose internal details, thus allowing you to change your internals without breaking the caller.
I have created a dll which consist of static class.I referred them in my web-jobs(webjob1,webjob2,etc..) created and deployed in azure.
Each web-job may access a method simultaneously.As we are using static class, it will create single memory in heap. Every web-job contains the reference value of that static class. My Question is, will it create any problem?
As per my understanding, C# works in a synchronous fashion. Thus, each web-job will wait in a queue to access the functions of static class. So any change made for the variables of that static class will reflect on other webjobs.Since static class have stand alone memory.
If my assumption is right, why should we keep such static helper class instead of normal one which we can instantiate and use it.
I am creating static class like this inorder to get some details from my db.
public static class StaticHelper
{
public static string GetValue()
{
using(IDBContext _DbContext = new sampleDBContext())
{
}
//Acessing values through this context
}
}
If I understand it correctly, you have multiple webjobs that have the same dependency on a dll. You have multiple instances of that website and use use the SDK but not the queue trigger.
Each webjob will be running as its own process and each instance of the website may have other instances of those webjobs (depends on if you have set single instance or multiple instance).
"Each web-job may access a method simultaneously" - yes but they will be in different processes so you will be safe in that case.
If that answers your question, more detail is really in learning about how .net and multiple processes handle static logic (not really webjobs specific). I would start with Jeffry Richter to learn that detail.
Each WebJob runs in its own process, which is distinct from the WebApp's process (w3wp). So they will each have their own copy of static variables.
IS Azure Webjobs have its own memory allocation?
I'm writing a custom task scheduler, and I would like to know if there is any way of setting the processor affinity for the current thread on Mono (running on Linux).
For the .NET runtime running on Windows, I've managed to get this to work by following Lenard Gunda's Running .NET threads on selected processor cores article; however, his approach fails on Mono (and Linux) because:
It requires a P/Invoke call to GetCurrentThreadId in the Kernel32.dll library.
The Process.Threads property currently returns an empty collection on Mono.
Does anyone please have a workaround for this?
lupus's answer was on the right track, but it took me some further research to get this implemented (such as the P/Invoke signature for sched_setaffinity and the resolution of libc.so.6). Here's the working code (excluding error-handling) in case anyone needs it:
[DllImport("libc.so.6", SetLastError=true)]
private static extern int sched_setaffinity(int pid, IntPtr cpusetsize,
ref ulong cpuset);
private static void SetAffinity(int processorID)
{
ulong processorMask = 1UL << processorID;
sched_setaffinity(0, new IntPtr(sizeof(ulong)), ref processorMask);
}
Edit: The above signature worked fine for my experiments, but refer to David Heffernan's answer (under my other question) for a suggested correction.
Note that you don't really have control of when a task gets run, that is up to the kernel.
Anyway, on Linux you will need to P/Invoke to sched_setaffinity() to bind a thread to a specific cpu.
See man sched_setaffinity for the interface.
How do I unload a DLL which has been loaded using DllImport in C#?
The most reliable way to unload an unmanaged DLL from a process that got loaded by a [DllImport] pinvoke declaration is to load it yourself, again, by pinvoking LoadLibrary(). That gives you a reliable handle to the DLL and works correctly even if the module name of the DLL is ambiguous. It doesn't have any affect at runtime, other than the Windows loader increasing the internal reference count on the DLL from 1 to 2.
You can then pinvoke FreeLibrary() twice to decrease the reference count to 0, passing it the IntPtr you got from LoadLibrary(). That unloads the DLL, as well as any dependent DLLs that got loaded.
Beware that you'll get very nasty failure when you try to pinvoke any exported function on the DLL again, any time after doing this. The pinvoke marshaller is unaware that the DLL isn't around anymore and will call the function at the address it thinks is still valid. Which bombs your program with an AccessViolation exception if you are lucky. Or runs a completely random bit of code if you are not so lucky and the address space formerly occupied by the DLL got re-used by another DLL. Anything can happen then, none of it good.
This should free a module previously loaded when you called P/Invoke function.
[DllImport("kernel32", SetLastError=true)]
static extern bool FreeLibrary(IntPtr hModule);
public static void UnloadModule(string moduleName)
{
foreach(ProcessModule mod in Process.GetCurrentProcess().Modules)
{
if(mod.ModuleName == moduleName)
{
FreeLibrary(mod.BaseAddress);
}
}
}
Based on Peters recommendation this works for me:
[DllImport("kernel32", SetLastError = true)]
private static extern bool FreeLibrary(IntPtr hModule);
public static void UnloadImportedDll(string DllPath)
{
foreach (System.Diagnostics.ProcessModule mod in System.Diagnostics.Process.GetCurrentProcess().Modules)
{
if (mod.FileName == DllPath)
{
FreeLibrary(mod.BaseAddress);
}
}
}
Late to the party, but I've made a tool to do this. It's supposed to run in Unity, but I think it can be adopted to other C# solutions. It's available here: https://github.com/mcpiroman/UnityNativeTool.
Please note that it is essentionally a hack (but often used hack, see Harmony), so I don't quite recommend using it at production code.
Since I came across the information here while I was looking around for information I figure I will contribute back what I ended up doing to fix an issue with the Sixense SDK on OSX IN UNITY. You'll see in there an implementation of dynamically loading/unloading a dylib on OSX:
https://gist.github.com/amirebrahimi/d7b02c01bcd3ca7da144