Warning: I started coding in c# 1 month ago with no pre-existent programming knowledge.
I'm using the following method to center the MessageBox inside the parent window:
How to get MessageBox.Show() to pop up in the middle of my WPF application?
I received warning claiming that the AppDomain.GetCurrentThreadId(); method is obsolete, so I found a "solution" here: http://www.pinvoke.net/default.aspx/kernel32/GetCurrentThreadId.html
As the code wouldn't work with uint, I changed it into int and then changed the AppDomain.GetCurrentThreadId(); into GetCurrentThreadId();
[DllImport("kernel32.dll")]
static extern int GetCurrentThreadId();
I've written a fairly complex database program that seems to work flawlessly so far and I understand most of the code behind it, so I would really appreciate if someone could explain to me what exactly I did with the mentioned "solution".
GetCurrentThreadId is a WinApi function, located in kernel32.dll (implemented in C). C# allows you to specify how to call this function via a mechanism called P/Invoke which dynamically finds the function in the specified library by its name, and properly marshals the arguments and return value, if any.
If .NET cannot provide what you need, it is generally fine to resolve to using P/Invoke, but note that this is not a 100% portable solution. On other platforms, the function is likely not to be present, but if you limit yourself to Windows (as you already do, looking at the answer you linked), it is okay.
Related
I need to use both C# and C++ in my OpenGL project. Ideally, the entire project is written only in C# using OpenTK (OpenGL functions ported to C#), GLFW.NET (aka ported GLFW), and GlmNet (GLM).
There's only one tiny place where I have to dynamically create an OpenGL texture using libraries that are only available for C++. In idea, this is not supposed to be a problem:
(make a DLL and use it in C#)
//In C++, Create DLL API for C# to use:
extern "C" MYDLL_API unsigned int GenerateTexture();
//in C#, bind an existing DLL.
[DllImport("MYDLL.dll", EntryPoint = "GenerateTexture", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern uint GenerateTexture();
This function should generate texture inside, set its bitmap and properties, and then return the handle of this texture. Spoiler - it immediately fails:
//C++. inside of a function GenerateTexture:
//(by the way, if that's important, on the side of C++, i use 'glad')
unsigned int texture;
glGenTextures(1, &texture);
^^^ sets texture to 0
glBindTexture(GL_TEXTURE_2D, texture);
^^^ throws access violation exception
I have googled about this issue and apparently, it's because OpenGL context is absent.
I have Glfw and OpenGL contexts all successfully initialized in C#, all functions are usable and workable. DLL itself is perfectly callable and I can even debug it. And everything is happening in one single thread.
Then why I cannot create a texture from a DLL?
first thought: maybe context is not magically passed to the DLL?
I searched how to pass the OpenGL context to the DLL, but everybody says when DLL is used, it becomes a part of the project, therefore context is automatically applied. OpenGL context is theoretically present in DLL.
Who or what fools me then?
A little handy problem-localizing test for you guys:
//Let's try creating a texture in C# itself
//right in the place where DLL is called
uint texture = glGenTexture();
^^^ returns a workable identifier 1.
uint textureFromDLL = DLL.GenerateTexture();
^^^ access violation.
So here it is apparent that the actual problem is that only this DLL is the one who cannot access OpenGL functions.
I have no idea what to think in this situation, maybe C#'s OpenTK and C++'s glad are wrapping different OpenGLs?:) it makes no sense to me. or, maybe people were wrong saying that openGL context is automatically present in DLL. In this case, my question is how can i transfer this almighty yet occult context to my pathetic DLL.
I tried to create and bind a texture in C#, and right after it, pass a handle to this texture to the DLL. but everything's futile, it throws access violation exception right on the next command where i call glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT). so yet again it needs full context, not just a handle.
Yes, I could rearrange the function so that C++ part does only the thing that has nothing to do with OpenGL. But it stresses me that something doesn't work when it theoretically should, and I'm afraid i will have serious problems if i need more DLL functionality in the future.
If someone needs to know it, my DLL is right inside the project, in Debug and Release folders. I use Visual Studio, C++20 (latest), C# .NET Core 3.1.
The answer. First theoretical part and below the actual steps to solve it.
I guess I'm not going to be the only person facing such an issue so this is a comprehensive answer for other people, based on my current experience.
Within one thread, OpenGL context holds, even while calling DLL.
Then why did access violation happen to me?
My assumption was that OpenGL function is being called, then inside, graphics driver tries to work on it and tries to access an existing OpenGL context in memory. If i didn't initialize OpenGL, it attempts to access memory that is not allocated, hence access violation exception occurs.
Well... The thing is... In reality, driver does not fail at all, because it's not even called! Turns out DLL was not even bound to the OpenGL functions to call them!
Actually, the C# situation is no different. neither of the functions are defined by default, they need to be bound dynamically, and I have the needed call Import(Glfw.GetProcAddress); in C# code. Without it, C# throws NullReferenceException when i call any OpenGL function.
And C++'s 'glad' is the same. All of the functions are just declarations which are function pointers to the actual driver functions, they need to be dynamically connected. Without it, these functions are pointing to nowhere.
They point to nowhere, therefore access violation error occurs. Again, context is here, it keeps its existence in DLL. The only thing needed is to make OpenGL function pointers valid in my C++ code too.
Holy user with the name 'BDL' precisely mentioned this idea in the comments with a suggestion to use gladLoadGLLoader in C++ to initialize glad.
I searched for some information about this function and its usage seems a little tricky: I have to pass some GLADloadproc which i have access to only in C#. While searching for how to accomplish it, i found a neighbouring 'glad' function gladLoadGL() which doesn't require any parameters to be passed. For a simple case like mine, this function is enough to initialize everything. And this is it! The easy function which truly solved my problem.
Actual Steps
If you have this exact situation where you want to occasionally access OpenGL functions from the DLL, just add a new function to your DLL, call it something like "Initialize":
//C++
void Initialize() {
gladLoadGL();
}
while in C#: (i guess it can be any other language, like Java, why not)
//right after you have initialized everything in C#
DLL.Initialize(); //initialize C++ part too.
You call it once. After it DLL is perfectly workable. Now everything is initialized in C# and everything is initialized in C++ codebase too. After this, you will be able to use OpenGL functions freely throughout the program and its DLL-s.
If that doesn't work, then I sincerely apologize for taking your time, it means the issue is yet again caused by something different.
These codes will set the windows calculator into a windows form application. But the question is how to use the NativeMethods.SetParent in the third line. Does it have special namespace?
System.Diagnostics.Process p = System.Diagnostics.Process.Start("calc.exe");
p.WaitForInputIdle();
NativeMethods.SetParent(p.MainWindowHandle, this.Handle);
Please help me to use NativeMethods in the third line.
Any help will be appreciated
I presume you are trying to "embed" the calculator within a WinForm? If so check out the following pinvoke method:
[DllImport("user32.dll")]
internal static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
http://www.pinvoke.net/default.aspx/user32.setparent
To embed the calculator window into a WinForm (or another control such as a Panel), just pass the Control.Handle as the second parameter.
There is no public NativeMethods class in .NET. It is considered good practice to put calls in a NativeMethods class, so this is probably what you are seeing.
You need to use P/Invoke to call Win32 API functions. See this tutorial.
stakx is onto something with his comment:
An obvious starting point would have been to study the original source of that line of code. Where did you copy it from? Can you find the declaration of NativeMethods.SetParent in the original source? (No need to answer, this is meant as a suggestion of what I would have done in this case.)
This is exactly the way you need to solve such problems.
The code snippet shown in the question was in fact copied from here. No, it doesn't compile when you copy and paste it into your project. It was never intended to. I wasn't trying to write a complete demo, but rather provide a brief sketch of what the required code might look like were you to write it yourself.
You do have to read the whole answer, not just the part with the light gray background. I know we're all programmers so we often think that we can understand everything just by looking at the code, but that's an unfortunate lie. I provided a link to the Windows SDK documentation for the SetParent function; you'll have to read that documentation, understand what the function does, and then write the P/Invoke declaration so that you can call it from your C# code.
Like Kendall says, calls to native Win32 functions are placed in a static class called NativeMethods, both by convention and by explicit recommendation from .NET design guidelines (enforced by tools such as StyleCop). My sample was following this common practice because I assumed .NET developers interested in Win32 interop would be familiar with this convention and follow it themselves when writing the P/Invoke definition.
As Nate alludes, some people find the website http://pinvoke.net/ to be a useful resource when writing P/Invoke definitions for Win32 functions. And it can often be. But you do have to make sure that you're not just copying and pasting code from there, either. I've seen a surprisingly large number of mistakes in the samples that they provide (and answered more than my fair share of Stack Overflow questions from people whose apps blew up when they used the incorrect code they copied from that website). You need to understand what the code you're using is doing and how it is supposed to work. Not only does that ensure you can catch any mistakes that it may contain, but it also keeps you from introducing serious bugs or worse, security holes, into your application.
I am working on a c# crawler/Poster project, it crawls wordpress blogs, sites, using WebClient to download content.
Wordpress sites use a bug or i don't know, of WebClient, for some reason it does not accept all cookies, from wordpress blogs, it may be a measure to stop auto bots, spammers.
So decided to use Sockets, but seems sockets also has a few problems, it sometimes does not return full response, so not reliable, but i found a good working code in VC++, i am trying to use it in C#, but i dont know vc++ at all.
Here is the code
How do i create a dll of the above code?
I have created a simple dll project using vc++ but unable include the above code in the project.
Updated Link to Code
You can use platform invokes, creating a declaration for each function you need. Here's an example of importing the MessageBox WinAPI function (note that this is not the same as the MessageBox class in .NET!)
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);
Now that I have downloaded your code, I can say this...
Even if we got this code to compile, we still have to do the normal heavy lifting of interop between C++ and C#. And the code isn't even ready for that. The http_download.h file is a big set of inline classes. And the instructions for making C++ Code invokable from C# is to long to list here. You would basically have to get this code to compile as a DLL. Then from the DLL either export a set of "C" functions that invoke your C++ to do what you want. Or convert these C++ classes into COM objects with a type library.
But let's analyze what you are really trying to do:
You want to crawl web pages, but WebClient doesn't work.
So I think the real question you want to ask:
Why doesn't WordPress accept my cookies with WebClient?
And I really don't know the answer, because you haven't shared your WebClient code or elaborated what you think may be the issue. But I bet it's an easily solved problem.
I'm certain WebClient will be 10x easier to use than than some C++ code hacked up as one .h file that doesn't look very pretty. And it will be 100x time easier than trying to put together a HTTP library using pure sockets (which is what WebClient is, but it supports all the features you need, but haven't realized yet).
Sorry if I'm curt. I'm trying to encourage you to think about this a better way than doing it the hard way.
Create a class library by using the C++ code and add it as a reference to your C# project.
[DllImport( "zlib32" )]
private static extern ZLibError compress2(
byte[] dest,
ref int destLength,
byte[] source,
int sourceLength,
ZLibQuality quality
);
every time I call this I get an MDA warning telling me the stack is imbalanced, which is a nightmare for debugging. I want to either turn this warning off, or fix the issue
This MDA raised to tell you that you have a problem with parameters type you are using for PInvoke call. Generally, it is very bad idea to turn it off since it warns about problem in your code and imbalanced stack leads to errors (sometimes hard to find) in future.
Usually, common mistake is selected matching for unmanaged type with managed one.
In your case, original defininition (I take a look to zlib125.zip):
ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
const Bytef *source, uLong sourceLen,
int level));
which can be traslated to if library was compiled with 64-bit support for unsigned long:
static int compress2(
byte[] dest,
ref ulong destLength,
byte[] source,
ulong sourceLength,
int level)
Ensure ZLibQualityenumeration is based on int. Probably, your error is usage int instead of ulong for both lengths.
As stated David Heffernan there are plenty other reasons to fail to find exact one give us link to library actually used for development if you still want to know.
traditional compilation original library with Visual C++ will result you get library with 32-bit support only, so original definition you provided in question is valid unless ZLibQuality enumeration is not int based
maybe you try to use library compiled for other calling convention such as cdecl instead of stdcall
maybe you try to use modified library where compress2 function takes additional parameters.
We can find whats wrong when we can see exact library you are using.
long or unsigned long usually 32-bit under Windows and mapped to int or uint respectively. Since you have troubles with original declaration I assumed that maybe you are using specific library with 64-bit support. Thanks to David Heffernan to point me makes my notice clearly.
You can use folowing resourses as reference:
A wiki for .NET developers - PInvoke.net is primarily a wiki, allowing developers to find, edit and add PInvoke* signatures, user-defined types, and any other information related to calling Win32 and other unmanaged APIs from managed code
PInvoke Interop Assistant
/Offtopic:
Why do you use you own implementation with self bindings to library? You can use:
DotNetZip - Zip and Unzip in C#, VB, any .NET language - DotNetZip is an easy-to-use, FAST, FREE class library and toolset for manipulating zip files or folders. Zip and Unzip is easy: with DotNetZip, .NET applications written in VB, C# - any .NET language - can easily create, read, extract, or update zip files. For Mono or MS .NET.
or ready to use 7-zip bindings: SevenZipSharp - Managed 7-zip library written in C# that provides data (self-)extraction and compression (all 7-zip formats are supported). It wraps 7z.dll or any compatible one and makes use of LZMA SDK.
The stack imbalance is because you have mis-matching calling conventions or mis-matching function declarations. I'd be very surprised if zlib32 was using stdcall calling convention. Surely that uses cdecl. I'd want to see your C++ declaration of that function before giving firmer advice.
Leave the warning on because it's finding bugs in your code, and fix the mis-matches, whatever they are.
There could be a real issue here, but I usually have to disable all Managed Debugging Assistants every now and then, since some of these magically get enabled. Be sure to check Debug | Exceptions node, then expand the Managed Debugging Assistants and make sure every one of these is disabled.
EDIT: You will have better luck replacing the P/Invoke with a C++/CLI wrapper that you create for compress2.
I have win32 DLL named VssSdkd.dll. It contains two classes with names VssSdkServiceLogin and VssSdkMsg.
I need to import the VssDskServiceLogin class, in C#. I am setting few properties of VssDskServiceLogin object and passing this to VssSdkMsg which in turn invokes some other method.
How can I achieve this using C#.
I have win32 DLL named VssSdkd.dll. It
contains two classes with names
VssSdkServiceLogin and VssSdkMsg.
In C#, I need to import the
VssDskServiceLogin class. In the class
are some attributes I need to set the
value for, sending the information to
VssSdkMsg and call another function
I need to achieve those things through
C# code. Is this possible, and if so,
how?
Classes compiled in C++ (and other Win32 languages) cannot be interoped with Dot NET languages. Structures may be if care is taken. Dot NET does have support for COM objects, though.
Native functions may be called from Dot NET languages if they're tagged with the [DllImport] attribute on the CLR side (and the appropriate DllImportAttribute properties are set) - and exported on the Win32 side. However, this is a non-trivial process. I would recommend grabbing a good book on the subject and starting from the top. SO is probably not a very good medium for addressing this issue.
You can do it with p/invoke and marshaling. Read about it, it's too complicated a subject to explain fully in a SO answer.
I believe it is sometimes possible in C# through P/Invoke, but when dealing with classes, this can get very, very difficult.
I'd highly recommend creating a C# wrapper for your DLL using Managed C++ instead.
I don't know that this link will solve your problem directly, but I expect you can find a good example of how to do this at Code Project. Managed C++ can be a little tricky until you get used to it, and I think the syntax changed from .NET 1.0/1.1 to .NET 2.0. Make sure you know what version of .NET you're targeting and search the Code Project site accordingly.
Possibly what you are looking for is interoperability with COM.
I haven't worked much on it, but can give you a sample code to start with.
[DllImport("user32.dll")]
private static extern int MessageBox(IntPtr hWnd, String
text, String caption, uint type);
static void Main(string[] args)
{
MessageBox(new IntPtr(0), "Hello, world!", "My box", 0);
}
This may be of help.