I have these in my c++ header file
#ifndef S2dll_H
#define S2dll_H
#ifdef S2dll_EXPORTS
#define S2dll_API __declspec(dllexport)
#else
#pragma message("automatic link to S2dll.LIB")
#pragma comment(lib, "S2dll.lib")
#define S2dll_API __declspec(dllimport)
#endif
class is declared like this
class S2dll_API Sample
{
//members here
}
a cpp file containing function definitions, constructors
void * __stdcall CreateS() //constructor
{
return new SDLL;
}
void __stdcall DestroyS(void * objPtr) //destructor
{
s* sObj = (s *) objPtr;
if (sobj)
delete sObj;
}
exporting/exposing this function
void __stdcall setvaluesDLL(void *ptr, int x, int y,int s, int p)
{
Sample *dll = (Sample *) ptr;
if (dll)
{
dll->setposition(c); //functions in the cpp file
dll->setlocation(x,y);
dll->setsize(s);
}
}
a .def file
LIBRARY BS2dll
EXPORTS
CreateS
DestroyS
setvaluesDLL
so I am trying to access it in my c# win form
made this to expose it
static internal class dllcall
{
[DllImport(#"adrress\S2dll.dll", CallingConvention = CallingConvention.StdCall)]
public static extern void setvaluesDLL(IntPtr ptr,int x, int y, int s, int p);
}
calling it in my winform
private void Assign_Click(object sender, EventArgs e)
{
dllcall.setvaluesDLL(ptr, x, y, s, p);//all values are int
}
I get this error:
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
been searching google and staring at this code for hours and every time I manage to solve a problem, a new one comes out whenever I call setvaluesDLL(//parameters)
EDITED:
IntPtr ptr is my main problem here and I have absolutely no idea how to use nor initialize it
You have to initialize first setvaluesDLL parameter value with CreateS() result. This method should be imported from the dll too. The same as DestroyS - to release memory properly
You have 5 arguments in your C++ file:
void __stdcall setvaluesDLL(void *ptr, int x, int y,int s, int p)
And only 4 in the C#:
public static extern void setvaluesDLL(int x, int y, int s, int p)
Also I don't think there's a direct equivalent to a void* pointer, so you might want to use unsafe code (you need to allow it in your project settings).
From what I know you cannot explicitly import a c++ class in C# (to initialize ptr in Assign_Click). Maybe you could write some functions in the dll to render it available to C# -- or you could delve into the assembly.
Related
I want to get the screen size of the primary screen, without adding any references (e.g. WinForms or Presentation). I found a similar question here, however there is no solution which doesn't include downloading or something like that.
But I want to make a method, which can be executed in the C# interactive on any other pc. Therefore I need a solution that doesn't reference other stuff than the standard (E.g. System, System.Core, ... is allowed).
I do know this is possible with
System.Windows.Forms.Screen.PrimaryScreen.Bounds;
but as this requires the System.Windows.Forms reference, it's not suitable for me. But basically the result of this snippet is what I want to get without references.
Here's an example I came up with.
I have noticed that it does not work correctly on High-DPI Screens. It will report the apparent resolution, not the actual resolution.
static void Main(string[] args)
{
var size = GetScreenSize();
Console.WriteLine(size.Length + " x " + size.Width);
Console.ReadLine();
}
static Size GetScreenSize()
{
return new Size(GetSystemMetrics(0), GetSystemMetrics(1));
}
struct Size
{
public Size(int l, int w)
{
Length = l;
Width = w;
}
public int Length { get; set; }
public int Width { get; set; }
}
[DllImport("User32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern int GetSystemMetrics(int nIndex);
If you don't want to use those libraries, You'll probably need to use native methods. I can't think of a way around this, as you'll need to communicate with the system any way you go.
A good place to start would be the source of System.Windows.Forms.Screen
Here's a link to the source. I bet you could strip down their code, and get the bare minimum.
I actually found a solution to this:
using System;
using System.Runtime.InteropServices;
static void Main()
{
EnumWindows(E, IntPtr.Zero);
Console.Write($"{_.Item1}x{_.Item2}");
}
struct R
{
int l;
int t;
public int r;
public int b;
public override string ToString() => $"{l},{t},{r},{b}";
public bool i() => l == 0 && r != 00;
}
static (int, int) _;
static bool E(IntPtr w, IntPtr l)
{
var r = new R();
GetWindowRect(w, ref r);
if (r.i() && _.Item1 == 0)
_ = (r.r, r.b);
return true;
}
delegate bool P(IntPtr w, IntPtr l);
[DllImport("user32.dll")]
static extern bool EnumWindows(P e, IntPtr l);
[DllImport("user32.dll")]
static extern bool GetWindowRect(IntPtr w, ref R r);
Main()
Paste this into your interactive and it should output the screen resolution - at least it does for me.
Don't ask me how it works, it's stumped together from different tutorials and pressed into the interactive. Therefore I can't guarantee this will work on every pc.
Could somebody else please test this?
I'm trying to use some native functions in C# over OpenGL.
I need to draw a Sphere and I read about gluSphere and looked at it on GL\glu.h, but receives a struct object as parameter:
typedef struct GLUquadric GLUquadric;
void APIENTRY gluSphere(GLUquadric *qobj,GLdouble radius,GLint slices,GLint stacks);
I need to create a struct so I can send it to gluSphere.
Is there some place or information of how is GLUquadric defined so I can write it and send it to gluSphere ?
[StructLayout(LayoutKind.Sequential)]
struct GLUquadric{
//What's here???
}
The bigger question is, if you actually want to use GLU at all. GLU has not been maintained for decades and didn't keep up with the development of the OpenGL API. GLU is not part of OpenGL proper, it's a companion library developed by SGI alongside OpenGL and published together with the OpenGL-1.1 specification. This first and latest version of GLU still assumes the presence of a fixed function pipeline and immediate drawing modes. Both have been removed from modern OpenGL.
I need to create a struct so I can send it to gluNewQuadric.
Actually there's no need to know what's inside this struct. It's defined as a opaque pointer type. Think of it as a class instance handle to which you don't have the interface; you can still pass it into the module implementing the class and call global methods on it, but you can't look inside. From the C# perspective it's an unmanaged pointer to something.
EDIT a code example (that I hope is valid C#)
[DllImport("glu32.dll")]
static extern IntPtr gluNewQuadric();
[DllImport("glu32.dll")]
static extern void gluDeleteQuadric(IntPtr quadric);
[DllImport("glu32.dll")]
static extern void gluSphere(IntPtr quadric, double radius, int slices, int stacks);
IntPtr quadric = gluNewQuadric();
gluSphere(quadric, 1, 10, 10);
gluDeleteQuadric(quadric);
That being said if you accept these caveats I wonder if it wouldn't make more sense to port some GLU implementation over to .net/CLI so that it can be used natively from C#.
You can of course also access GLU through unmanaged interfaces. Now my personal experience with C# is little (I've got more experience with F#) and I never left the managed grounds doing unmanaged things. But from my understanding what you have to do there is just define an integer variable large enough to hold a native pointer (and if I'm not mistaken, there already should be such a integer type for holding unmanaged pointers) and use that for the GLUQuadric* type.
Looks like searching in google for
"struct GLUquadric"
didn't give any information or clue... But searching for
"struct GLUquadric{ "
took me to the place I wanted:
OGLES_GLU.h
Struct I found and used and WORKS is:
[StructLayout(LayoutKind.Sequential)]
public struct GLUquadric
{
int normals;
bool textureCoords;
int orientation;
int drawStyle;
}
So now I can use:
[DllImport("glu32.dll")]
static extern void gluSphere(ref GLUquadric qobj, double radius, int slices, int stacks);
public static void Sphere(ref GLUquadric qobject, double Radius, int Slices, int Stacks)
{
gluSphere(ref qobject, Radius, Slices, Stacks);
}
OpenGL draws spheres now.
NOTE: When drawing spheres in imported openGL function, DO NOT CALL gluDeleteQuadric();
Let GC do it's work, just declare a new GLUQuadric() and send it as a ref to gluSphere, else you will have memory problems in your program.
To compliment datenwolf's answer which is not valid in my case:
The implementation of my program is this way:
[StructLayout(LayoutKind.Sequential)]
public struct GLUquadric
{
int normals;
bool textureCoords;
int orientation;
int drawStyle;
public void Init(int norm, int draw, int orient, bool textCoor)
{
normals = norm;
drawStyle = draw;
orientation = orient;
textureCoords = textCoor;
}
}
Use is:
public static void DrawSphere(T Radius, Int32 Slices, Int32 Stacks,
GLU.QuadricDrawStyles Style, GLU.QuadricNormals Normal, Color color)
{
OpenGL.SetColor(color);
GLU.GLUquadric quadric = new GLU.GLUquadric();
quadric.Init((int)Normal, (int)Style, 0, false);
GLU.Sphere(ref quadric, (dynamic)Radius, Slices, Stacks);
}
Implementation is full OO, so every Sphere is isolated from static GL Function as gluQuadricDrawStyle and gluQuadricNormals so leaving struct empty is NOT valid since it will draw nothing.
I have a C# DLL, whose code derives from a base class, which is written in managed C++. (I don't have any control over the base class code)
This base class (which is in managed C++) has a member
int *buffer
is expected to be memset (filled with Zeros) by the derived class (which is in C#). The derived class knows the size of the buffer.
I am using unsafe context, to access the member "int *buffer" of the base class, in the derived class. Please let me know is there any way special way to memset the buffer in "unsafe" context in c#.
I already looked into this What is the equivalent of memset in C#? for details, but I would like to know is there something specifically for "unsafe" context.
Background : This is a conversion project, where the derived class itself was in managed c++ before. Now I am converting the derived class DLL alone to C#. Also I have no control over the base class code! The current code flow is as follows: Only the derived class knows the size of the buffer. The base class creates a memory for that particular size, by getting the size of the buffer from derived, but it doesn't zero fill. The derived class Zero fills it first and then need to appropriately fill the buffer with its contents. Though strange, that is how it is.
Thanks!
Well, there is... memset. Why settle for a replacement when you can p/invoke the real thing?
[DllImport("msvcrt.dll", EntryPoint = "memset", CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
public static extern IntPtr MemSet(IntPtr dest, int c, IntPtr count);
Taken from pinvoke.net
edit
As #Hans rightfully mentions in the OP comments, this is useless if you don't already know the size of *buffer.
You can code it on your own:
void memset( byte* buffer, int value, int size )
{
for( int i = 0; i < count; i++)
{
*( buffer + i ) = value;
}
}
Or you can use an API for this. Actually RtlZeroMemory sets values to zero. It's not actually memset.
[DllImport("kernel32.dll")]
static extern void RtlZeroMemory(IntPtr dst, int length);
RtlZeroMemory(buffer, bufferLength);
RtlZeroMemory is not actually an entry point in kernel32. If yo want something like that, use this in C#
public static unsafe void ZeroMemory(IntPtr Safebuffer, int count)
{
if (count == 0) return;
byte* buffer = (byte*)Safebuffer.ToPointer();
memset(buffer, count);
}
public static unsafe void ZeroMemory(byte* buffer, int count)
{
if (count == 0) return;
while (count-- > 0)
{
buffer[count] = 0;
}
}
Perhaps the problem i have is a bit specific but I'm sure the solution would be interesting for a lot of people.
Now to the point. I have an ActiveX control that plays streaming video. My goal is to get to every frame it plays and display them in external c# application over some windows control, a panel, for instance.
Here is the sample DirectShow transform filter:
STDMETHODIMP CTransform::Transform(BSTR bsResource, struct U_VideoFrame *pInFrame, struct U_VideoFrameData **pOutFrameData)
{
//Must allocate memory this way, the output size must be equal to input size
*pOutFrameData = (U_VideoFrameData*)CoTaskMemAlloc(sizeof(U_VideoFrameData));
(*pOutFrameData)->pFrame = (BYTE*)CoTaskMemAlloc(pInFrame->Frame.nLength);
(*pOutFrameData)->nLength = pInFrame->Frame.nLength;
//Now transform data contained in (*pOutFrameData)->pFrame;
//We simply copy data here
memcpy((*pOutFrameData)->pFrame, pInFrame->Frame.pFrame, pInFrame->Frame.nLength);
return S_OK;
}
My idea is that somewhere inside this method I should place a callback function that will call my managed code and pass pInFrame to it. How can I do it? Please help
P.S. I have read the great article Howto implement callback interface from unmanaged DLL to .net app. It works as described (of course). However, when I modify the code above to this:
typedef int (__stdcall * Callback)(const char* text);
static Callback Handler = 0;
extern "C" __declspec(dllexport)
void __stdcall SetCallback(Callback handler) {
Handler = handler;
}
extern "C" __declspec(dllexport)
void __stdcall TestCallback() {
int retval = Handler("hello world");
}
// CTransform
STDMETHODIMP CTransform::Transform(BSTR bsResource, struct U_VideoFrame *pInFrame, struct U_VideoFrameData **pOutFrameData)
{
//Must allocate memory this way, the output size must be equal to input size
*pOutFrameData = (U_VideoFrameData*)CoTaskMemAlloc(sizeof(U_VideoFrameData));
(*pOutFrameData)->pFrame = (BYTE*)CoTaskMemAlloc(pInFrame->Frame.nLength);
(*pOutFrameData)->nLength = pInFrame->Frame.nLength;
//Now transform data contained in (*pOutFrameData)->pFrame;
//We simply copy data here
memcpy((*pOutFrameData)->pFrame, pInFrame->Frame.pFrame, pInFrame->Frame.nLength);
if (Handler != 0)
int retval = Handler("Transform");
return S_OK;
}
then the event does not fire from Transform method. TestCallback() method works
I'm stuck. Any help will be greatly appreciated.
As I understand it, marking an method as unsafe will disable some of the CLR checks on that code, but does this have any effect on the rest of the system which is safe, other than the fact that the DLL/EXE can not run in a untrusted environment.
In particular,
Are they are any safety checks that will not work on the complete dll because it is marked as unsafe?
If a DLL is marked as unsafe, but the methods marked as unsafe are
not actually called, is this the same as if the DLL is marked as
safe?
Are they any run-time benefits on keeping the unsafe code in a
separate DLL?
I have the problem with redrawing nested controls on 64-bit windows as detailed here and the one the solutions (the one that appears to work) involves unsafe code and I would like to understand the effect that adding this code has to my project.
An unsafe code is capable of corrupting the managed heap. As such, anything that runs in the same process can be affected.
This includes all other libraries and potentially all other AppDomains in the same process.
UPDATE
Here is an example:
http://blogs.msdn.com/b/tess/archive/2006/02/09/net-crash-managed-heap-corruption-calling-unmanaged-code.aspx
UPDATE 2
Is unsafe code that is written
diligently bad?
No. There are tons of unsafe code in the .NET framework itself. Examples many, but here is one in the System.String:
public static unsafe string Copy(string str)
{
if (str == null)
{
throw new ArgumentNullException("str");
}
int length = str.Length;
string str2 = FastAllocateString(length);
fixed (char* chRef = &str2.m_firstChar)
{
fixed (char* chRef2 = &str.m_firstChar)
{
wstrcpyPtrAligned(chRef, chRef2, length);
}
}
return str2;
}
The answer to your question is: The unsafe keyword does not mean "unsafe", it means "potentially unsafe". The compiler and framework cannot work to make certain that it's safe. It is up to you to make certain that the code cannot perform unsafe reads or writes to memory.
I would strongly encourage you to follow this advice given in the article you linked:
1) Redesign the application to have less containers and reduce the number of nesting levels.
If you're using containers for the sole purpose of control arrangement, write your own container that can do all the arrangement with one level.
Updated
You can modify the code in that article so that it doesn't use pointers (i.e. doesn't require the unsafe keyword). Keep in mind that this will now require marshalling which means extra copying. This is probably a good thing because the original code is passing a WINDOWPOS pointer from the OS to BeginInvoke which does not execute during the same dispatch event that the OS generated the pointer in. In other words, that code was smelly already.
internal class MyTabPage : TabPage
{
private const int WM_WINDOWPOSCHANGING = 70;
private const int WM_SETREDRAW = 0xB;
private const int SWP_NOACTIVATE = 0x0010;
private const int SWP_NOZORDER = 0x0004;
private const int SWP_NOSIZE = 0x0001;
private const int SWP_NOMOVE = 0x0002;
[DllImport("User32.dll", CharSet = CharSet.Auto)]
extern static int SendMessage(HandleRef hWnd, int msg, int wParam, int lParam);
[DllImport("User32.dll", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
extern static bool SetWindowPos(HandleRef hWnd, HandleRef hWndInsertAfter,
int x, int y, int cx, int cy, int flags);
[StructLayout(LayoutKind.Sequential)]
private class WINDOWPOS
{
public IntPtr hwnd;
public IntPtr hwndInsertAfter;
public int x;
public int y;
public int cx;
public int cy;
public int flags;
};
private delegate void ResizeChildDelegate(WINDOWPOS wpos);
private void ResizeChild(WINDOWPOS wpos)
{
// verify if it's the right instance of MyPanel if needed
if ((this.Controls.Count == 1) && (this.Controls[0] is Panel))
{
Panel child = this.Controls[0] as Panel;
// stop window redraw to avoid flicker
SendMessage(new HandleRef(child, child.Handle), WM_SETREDRAW, 0, 0);
// start a new stack of SetWindowPos calls
SetWindowPos(new HandleRef(child, child.Handle), new HandleRef(null, IntPtr.Zero),
0, 0, wpos.cx, wpos.cy, SWP_NOACTIVATE | SWP_NOZORDER);
// turn window repainting back on
SendMessage(new HandleRef(child, child.Handle), WM_SETREDRAW, 1, 0);
// send repaint message to this control and its children
this.Invalidate(true);
}
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_WINDOWPOSCHANGING)
{
WINDOWPOS wpos = new WINDOWPOS();
Marshal.PtrToStructure(m.LParam, wpos);
Debug.WriteLine("WM_WINDOWPOSCHANGING received by " + this.Name + " flags " + wpos.flags);
if (((wpos.flags & (SWP_NOZORDER | SWP_NOACTIVATE)) == (SWP_NOZORDER | SWP_NOACTIVATE)) &&
((wpos.flags & ~(SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE)) == 0))
{
if ((wpos.cx != this.Width) || (wpos.cy != this.Height))
{
BeginInvoke(new ResizeChildDelegate(ResizeChild), wpos);
return;
}
}
}
base.WndProc(ref m);
}
}
Note: The change in WINDOWPOS from value type to reference type is intentional. Using a reference type reduces the number of copies to just one (the initial marshal)(**).
Updated Again
I just noticed that the code originally made the p/invoke declarations public. Never, ever expose p/invoke outside of a class(*). Write managed methods that invoke private p/invoke declarations if your intent is to expose the capabilities provided; which in this case is not true, the p/invoke is strictly internal.
(*) Ok, one exception. You're creating a NativeMethods, UnsafeNativeMethods, etc. Which is the recommended way to do p/invoke by FxCop.
Updated
(**) I was asked (elsewhere) to describe precicely why using a reference type here is better, so I've added that info here. The question I was asked was, "Doesn't this add memory pressure?"
If WINDOWPOS was a value type, this would be the sequence of events:
1) Copy from unmanaged to managed memory
WINDOWPOS wpos = Marshal.PtrToStructure(m.LParam, typeof(WINDOWPOS));
2) Second copy?
BeginInvoke(new ResizeChildDelegate(ResizeChild), wpos);
Wait! The signature of BeginInvoke is (Delegate, params object[]). That means wpos is going to get boxed. So yes, a second copy occurs here: The boxing operation.
BeginInvoke will add the delegate and object[] to an invocation list and post a registered window message. When that message is removed from the queue by the message pump, the delegate will be called with the object[] parameters.
3) Unbox and copy for ResizeChild call.
At this point you can see that the number of copies isn't even the issue. The fact that it gets converted to a reference type (boxed) means that we are better off making it a reference type to begin with.