When I was marshalling EnumChildWindows, I declared the function like that: [DllImport("user32.dll",SetLastError=true)] public static extern bool EnumChildWindows( IntPtr hWndParent, User32Functions.EnumWindowsCallback lpEnumFunc, IntPtr lParam );
The point is, why do you need to pass a class or struct as the third parameter? I followed the MSDN recommendation and called the function like that: GCHandle gch=GCHandle.Alloc(this.twHandles); User32.EnumChildWindows(handleParent,this.enumThreadCallback,(IntPtr)gch); gch.Free();
Here this.twHandles is a text writer, which i later (in the callback function) use like so: private bool CaptureEnumThreadWindows(int handle, IntPtr param) { GCHandle gch=(GCHandle)param; TextWriter tw=(TextWriter)gch.Target; twHandles.Write(handle.ToString()+" "); twHandles.Flush(); return true; }
Anyway, MSDN recommends to use GCHandle , 'so the delegate does not get moved by GC before the call ends, however I was trying to use without GCHandle, just passing IntPtr.Zero as the last parameter and it works anyway. Frankly I don't understand how this (GCHandle) can prevent the delegate from being moved by GC, but that's what MSDN says. (see GCHandle sample)
User 929285
Posts
-
Passing a Class to an Unmanaged function as parameter -
File sizenew FileInfo("myPath").Length
-
How to get an Array allocated in Unmanamed codeIf we can use StreamReader or other managed call for asyncronous calls, then please let me know . how can i do the same. FileStream::BeginRead FileStream::EndRead
-
How to get an Array allocated in Unmanamed codeThere are two ways you can call ReadFile: First way: import the function:
[DllImport(S"Kernel32.dll", EntryPoint="ReadFile", CharSet=CharSet::Auto)] extern "C" Boolean ReadFileNative(IntPtr hFile,StringBuilder *lpBuffer, UInt32 nNumberOfBytesToRead, UInt32 *lpNumberOfBytesRead, Int32);
Here's a function that returns text from a file:String *GetFileTextWithImport(String *fileName){ FileStream *fs=new FileStream(fileName,FileMode::Open); //Wrapping a handle with HandleRef guarantees that //the managed object is not garbage collected //until the platform invoke call completes. HandleRef hRef=HandleRef(fs,fs->Handle); StringBuilder *sbText=new StringBuilder(fs->Length); UInt32 uiToRead=0; ReadFileNative(hRef.Handle,sbText,fs->Length,&uiToRead,0); fs->Dispose(); return sbText->ToString(); }
Second Way: just call ReadFile without importingString *GetFileText(String *fileName){ FileStream *fs=new FileStream(fileName,FileMode::Open); HandleRef hRef=HandleRef(fs,fs->Handle); IntPtr ptrText=Marshal::AllocHGlobal(fs->Length); DWORD uiToRead=fs->Length, uiRead=0; ReadFile((HANDLE)hRef.Handle,ptrText.ToPointer(),uiToRead,&uiRead,NULL); String *strRet=Marshal::PtrToStringAnsi(ptrText); Marshal::FreeHGlobal(ptrText); fs->Dispose(); return strRet;
P.S. By the way, why not use the System.IO.StreamReader? -
Delegates in Managed C++Here's a simple example:
#using using namespace System; public __delegate Int32 FactorialCallback(Int32,Int32*); public __gc class Factorial{ public: FactorialCallback *fc; Factorial(){ this->fc=new FactorialCallback(this, GetFactorial); } Int32 GetFactorial(Int32 iSeed, Int32 *iNumberOfCircles){ (*iNumberOfCircles)++; return (iSeed==0)?1:(GetFactorial(iSeed-1,iNumberOfCircles)*iSeed); } Void FactorialComplete(IAsyncResult *ar){ Int32 iNumberOfCircles; Int32 iResult=this->fc->EndInvoke(&iNumberOfCircles,ar); Console::WriteLine(S"The result is {0}, nuber of circles is {1}",iResult.ToString(),(iNumberOfCircles-1).ToString()); Console::Read(); } }; int _tmain() { Factorial *fact=new Factorial(); Int32 dummy=0; AsyncCallback *ac=new AsyncCallback(fact,&Factorial::FactorialComplete); fact->fc->BeginInvoke(5,&dummy,ac,NULL); Console::WriteLine(S"Main complete"); Console::Read(); return 0; }
-
marshalling COM to .NET problemCould someone please help with marshalling to .NET. I posted this question here, not in C#, 'cause I know for sure the mistake is somewhere in .idl or cpp file. I have a Win32 C++ project with the following three files: //tlbsamp.cpp/////////////////////////////////////////////////// #include interface ITest{bool MyFunc();}; class Test:public ITest{ int i; public: Test(){i=10;} int MyFunc(){return i;} }; ITest* __stdcall MyDll_CreateTest(){ return new Test(); } int __stdcall MyDll_CreateInt(){ return rand();} BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) {return TRUE;} //tlbsamp.def////////////////////////////////////////////////////////// LIBRARY TLBSamp DESCRIPTION 'Sample DLL' EXPORTS MyDll_CreateTest MyDll_CreateInt //tlbsamp.idl///////////////////////////////////////////////////////////// import "oaidl.idl"; import "ocidl.idl"; [ uuid(983EE63A-7FB0-494a-AD63-14F48347DB7A), lcid(0x0409), version(1.0) ] library TLBSample { [object,uuid( 1F707072-05C6-4501-AD74-CFD57AB8002C)] interface ITest:IUnknown {int MyFunc ();} [ version(1.0), dllname("TLBSamp.dll")] module MyDllFunctions { [entry("MyDll_CreateTest")] ITest* __stdcall CreateTest(); [entry("MyDll_CreateInt")] int _stdcall CreateInt(); } }; I am compiling the project and get tlbsamp.dll ,tlbsamp.tlb, tlbsamp.lib, then I create a c# project, AddReference->COM-> Browse, all the .tlb file. In object browser I can see my ITest interface with MyFunk function. Here's the c# code. using System; using System.Runtime.InteropServices; using TLBSample; namespace Test_Call_MSDN_Dll { class Class1 { [DllImport(@"E:\MyProgs\NET\TLBSamp\debug\tlbsamp.dll")] public static extern TLBSample.ITest MyDll_CreateTest(); [DllImport(@"E:\MyProgs\NET\TLBSamp\debug\tlbsamp.dll")] public static extern Int32 MyDll_CreateInt(); [STAThread] static void Main(string[] args) { Console.WriteLine(MyDll_CreateInt().ToString());//OK-works fine ITest spClass=MyDll_CreateTest();//ExecutionEngineException(???) Console.WriteLine(spClass.MyFunc().ToString()); Сonsole.Read(); } } } What am I doing wrong? Thanks in advance!
-
multiple Application states?Please have a look at the following log my application has made: 9:33:38Application Starting (Application_Start) 9:33:38Application variable 'server' is really null 9:33:39Session Starting (Session_Start) 9:37:12Application Starting (Application_Start) 9:37:12Application variable 'server' is really null 9:37:12Session Starting (Session_Start) So the question is how is it ever possible that another instance of my web application is starting after 5 min when I have session timeout set to 30 min? I have problem with that because in each case the application creates new instances of application items, so my application state is not syncronized. Thanks in advance!
-
chat application in ASP.NET -
Icon image loses quality after deserializationI meant, in this example no image quality loss can be observed.
-
Icon image loses quality after deserializationButton button1=new Button(); button1.Parent=this; button1.Bounds=new Rectangle(20,20,256,256); button1.Image=new Bitmap(@"C:\Windows\soap bubbles.bmp"); FileStream fs=new FileStream("iconser.bin",FileMode.OpenOrCreate,FileAccess.Write,FileShare.None); BinaryFormatter bf=new BinaryFormatter(); bf.Serialize(fs,button1.Image); fs.Flush(); fs.Close(); FileStream fsOut=new FileStream("iconser.bin",FileMode.Open,FileAccess.Read,FileShare.None); Image img=(Image)bf.Deserialize(fsOut); Button btn=new Button(); btn.Bounds=new Rectangle(300,20,256,256); btn.Parent=this; btn.Image=img;