切换到VS2010后,托管调试助手在从C#应用程序调用非托管C++函数时显示有关不平衡堆栈的错误.
通常的嫌疑人似乎没有引起这个问题.还有别的我应该检查一下吗?VS2008构建的C++ DLL和C#应用程序从来没有出现问题,没有奇怪或神秘的错误 - 是的,我知道这并不意味着什么.
以下是检查的内容:
C#:
[DllImport("Correct.dll", EntryPoint = "SuperSpecialOpenFileFunc", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, ExactSpelling = true)]
public static extern short SuperSpecialOpenFileFunc(ref SuperSpecialStruct stuff);
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct SuperSpecialStruct
{
public int field1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string field2;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string field3;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string field4;
public ushort field5;
public ushort field6;
public ushort field7;
public …Run Code Online (Sandbox Code Playgroud) 我试图制作绝对最简单的最小例子,说明如何在C#中向C++ DLL传递字符串.
我的C++看起来像这样:
using std::string;
extern "C" {
string concat(string a, string b){
return a + b;
}
}
Run Code Online (Sandbox Code Playgroud)
像标题一样
using std::string;
extern "C" {
// Returns a + b
__declspec(dllexport) string concat(string a, string b);
}
Run Code Online (Sandbox Code Playgroud)
我的C#是
[DllImport("*****.dll", CallingConvention = CallingConvention.Cdecl)]
static extern string concat(string a, string b);
}
Run Code Online (Sandbox Code Playgroud)
我用它来调用它:Console.WriteLine(concat("a","b"));
但是这会产生System.AccessViolationException.这似乎是处理最琐碎的事情,但我完全坚持下去.当我尝试使用"添加"功能进行类似的实验,这个功能需要两个双打并且返回一个双重而没有问题.
我开始用C#编写调试器,以调试我的操作系统上的任何进程.目前,它只能处理断点(HW,SW和内存),但现在我想显示进程的操作码.
我的第一次尝试是使用nidsasm(NASM),但这不合适,因为启动后a.Net应用程序汇编程序指令与ndisasm(使用CheatEngine测试)不同.
所以我搜索了一段时间,发现dbghelp.dll中的一些方法,可以调用它们列出所有加载的模块和符号(加上基地址).好吧,我的尝试是,用SharpDisasm分别拆解所有模块.
我ProcessModuleCollection modules = ProcessData.Instance.MPMR.ReadProcess.Modules;用来获取进程的所有加载模块.这非常有效.
现在我尝试加载MainModule的符号,但此时,我坚持实现.我用p/Invoke和SymInitialize等其他必要的函数实现了SymEnumSymbols函数.
当我使用例如"User32.dll"的BaseAddress调用它时,所有符号都打印得很完美,但对于MainModule,我没有得到任何符号.
这是来自CheatEngine的截图: 从Cheat Engine获得的符号
正如你所看到的,有像"Form1_Load"这样的符号,我的实现并没有这些符号.
这是必要的代码示例:
if (!DebugApi.SymInitialize(ProcessData.Instance.MPMR.M_hProcess, null, false))
{
var err = Marshal.GetLastWin32Error();
//throw new Exception("GetMemoryInfo failed : GetLastError() : " + new Win32Exception(err).Message);
Console.WriteLine("GetMemoryInfo failed : GetLastError() : " + new Win32Exception(err).Message);
return;
}
if (!DebugApi.SymEnumSymbols(ProcessData.Instance.MPMR.M_hProcess, (ulong)ProcessData.Instance.MPMR.ReadProcess.MainModule.BaseAddress, "!", DebugApi.EnumSyms, IntPtr.Zero))
{
var err = Marshal.GetLastWin32Error();
//throw new Exception("GetMemoryInfo failed : GetLastError() : " + new Win32Exception(err).Message);
Console.WriteLine("GetMemoryInfo failed : GetLastError() : " + new Win32Exception(err).Message);
return;
} …Run Code Online (Sandbox Code Playgroud) 我正在寻找一种在C#或.NET中执行指针操作的方法.
我想做一些非常简单的事情
有一个指针IntPtr我想获得指向前2个字节的IntPtr对象.
我读了一些帖子,说这个愚蠢的片段会起作用......
IntPtr ptr = new IntPtr(oldptr.ToInt32() + 2);
Run Code Online (Sandbox Code Playgroud)
但我怀疑这个语句是否也适用于64位机器(因为在那里寻址是64位).
我发现这种优雅的方法来添加偏移量,但不幸的是只在.NET 4.0中http://msdn.microsoft.com/en-us/library/system.intptr.add%28VS.100%29.aspx
这是我到目前为止:
Dim bProcess = Process.GetProcessesByName("By").FirstOrDefault
If bProcess IsNot Nothing Then
SwitchToThisWindow(bProcess.MainWindowHandle, True)
Else
Process.Start("C:\Program Files\B\B.exe")
End If
Run Code Online (Sandbox Code Playgroud)
它有两个问题.
那么这样做的正确方法是什么?
具有中等大小(40多个函数)的C API,需要从C#项目调用.这些函数在逻辑上分解,形成一些类,这些类将呈现给项目的其余部分.
在稳健性,可维护性,部署......方面,是否有任何客观理由倾向于使用P/Invoke或C++/CLI来实现该API下的互操作性?
我能想到的问题可能是,但没有问题的是:
我不确定的问题是:
还要别的吗?
我偶然发现了一个为Microsoft自己的非托管DLL生成P/Invoke签名的工具:PInvoke Interop Assistant
是否有类似的工具将为第三方非托管DLL生成P/Invoke签名?
或者,任何方式将第三方DLL提供给PInvoke Interop Assistant
编辑:我试图解决的实际问题
我打算使用作为COM对象公开的各种对象.为了使它们更容易使用,我想将它们包装为C#对象.对此最好的方法是什么?
我有以下功能:
public static extern uint FILES_GetMemoryMapping(
[MarshalAs(UnmanagedType.LPStr)] string pPathFile,
out ushort Size,
[MarshalAs(UnmanagedType.LPStr)] string MapName,
out ushort PacketSize,
ref Mapping oMapping,
out byte PagesPerSector);
Run Code Online (Sandbox Code Playgroud)
我想这样称呼:
FILES_GetMemoryMapping(MapFile, out size, MapName,
out PacketSize, null, out PagePerSector);
Run Code Online (Sandbox Code Playgroud)
不幸的是,我无法传递null一个需要类型的字段ref Mapping而且没有投射我已经尝试修复此问题.
有什么建议?
我使用Pinvoke实现本机(C++)代码和托管(C#)代码之间的互操作性.我想要实现的是从本机代码中获取一些文本到我的托管代码中.为此,我尝试了很多东西,例如通过ref传递字符串/ stringbuilder,使用[IN]和[OUT],Marshaling到LPSTR,从函数返回字符串等,但在我的情况下没有任何作用.任何有关一些小代码的帮助都将受到高度赞赏.