gpt4 book ai didi

c# - 在 C# 中为 p/invoke 创建一个基本的 C++ .dll

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:40:13 28 4
gpt4 key购买 nike

我是一名 C# 程序员,不幸的是,由于年龄和经验,我没有机会在我的学习中经历 C++ 编程时代的奢侈——其中很多东西对我来说都是神秘和新鲜的.不是真的在这里争论学习或不学习的重要性,但我需要一些帮助来解决一件微不足道的事情。

问题

我需要帮助将我的 C++ 代码打包成 .dll。我没有使用 C++ 的经验,并且在制作我可以从 (Visual Studio 2010) 中 p/调用的工作 .dll 时遇到了很大的困难。请继续阅读以获取更多详细信息以及我尝试打包的代码。

详情

我有一些代码需要在非托管环境中运行。一般情况下,一个简单的p/invoke就适合这个任务。连接一些 [ImportDll] 就可以了。最坏的情况我有时可以使用编码。然而,由于我尚未真正发现的原因,这对于我目前的任务来说似乎是不可能的。

我正在尝试从旧的非托管 C++ 应用程序中生成的 owner drawn list box 中读取一些数据,并从中获取文本。我已经看到了几个如何执行此操作的示例 - 但它们是在较旧的 VB6 代码中。

我发现了 C++ 的等价物,但这也不适合我。就算是p/invoke,内存的搬家,需要怎么操作,好像也很麻烦。这个过程非常简单。

I need to create a simple C++ .dll that runs the method I need in unmanaged code, and populates a variable with the result.

这听起来很愚蠢,我不知道该怎么做。我试过在 Visual Studio 中运行简单的 C++ 向导(使用 Visual Studio 2010),但我运气不好。我希望有人可以帮助我解决这个问题,也许可以解释发生了什么,以便我可以从中学习。

这是我需要放入 .dll 的代码。

目的是让 hListWnd 在 C# 中作为 IntPtr 传递,index 将是一个简单的 Int32 ,而 outputResult 将用于完成这项工作所需的一切。在其他 p/invoke 情况下,我已经看到使用 System.Text.StringBuilder 完成此操作,但我愿意使用任何 来使这项工作正常进行。

void GetListItemData( HWND hListWnd, long index, char *outputResult )
{
int result;
DWORD processID;
HANDLE hProcess;
char *itemData;
char sDataRead[5];
DWORD bytes;
DWORD lListItemHold, lListItemDataHold;
*outputResult=0;

if( hListWnd )
{
GetWindowThreadProcessId( hListWnd, &processID );

hProcess=OpenProcess( 0x10|0xf0000|PROCESS_VM_READ, 0, processID );

if( hProcess )
{
lListItemHold=(DWORD)SendMessage( hListWnd, LB_GETITEMDATA, index-1, 0 );
lListItemHold=lListItemHold+24;

result=ReadProcessMemory( hProcess, (void *)lListItemHold, &sDataRead, 4, &bytes );
if( !result )
{
RaiseWinErr();
}

memcpy( &lListItemDataHold, &sDataRead, 4 );
lListItemDataHold=lListItemDataHold+6;

ReadProcessMemory( hProcess, (void *)lListItemDataHold, outputResult, 16, &bytes );

CloseHandle( hProcess );
}
}
}

如果有人可以帮助我,我在这里乞求。这对我来说已经成为一个非常令人沮丧的问题。我曾尝试使用 RtlMoveMemoryReadProcessMemory p/invoke 在 C# 中重现此内容,但无济于事。我已经找了好几天了,并且不断地得出毫无意义的结果。我知道有些代码没有多大意义(有人问我为什么需要 +6 以及 +24 是什么,等等),绝对的事实是我不 完全知道。我所知道的是 owner drawn list box 在其上使用了一些图形,这些偏移量的目的是检查绘制图形区域以外的数据,因为 List Item 的实际结构未知。

我尝试过的另一种方法是使用 IAccessible 库将我的项目检索为 Accessibility.dll。这也没有结果。我还尝试了 pinvoke.net 的 ManagedWinApi,那里的库没有证明任何成功。

我知道这段代码有效。它只是在 C# 中不起作用。我的理论是,使用 [DllImport] 在 C# 中调用它会给我想要的结果。

再次感谢任何人提供的帮助。

最佳答案

第三个参数需要是一个 byte[],编码为 char*,大小为 16。

如果您查看 ReadProcessMemory 的文档,它需要一个缓冲区和一个大小,并且此函数将大小作为 16 字节传递。这意味着您将需要一个 16 字节的数组。运行时应该非常乐意编码(marshal)大小为 16 的 byte[]。注意不要将 C++ char 与 C# char 混合使用 - C# char 实际上是 Windows 上的 C++ wchar_t。 C++ char 是 C# 的 byte。

并不是说我对这些函数的工作原理有任何实际想法 - 我只是跟踪了第三个参数的用法,它实际上只传递给了 ReadProcessMemory,其参数记录得很清楚。

要打包成一个 .dll(假设你没有其他东西可以进入那个 .dll),你想在开头添加一些东西来要求 C++ 编译器不要破坏名称并为你导出它, 将其作为第一行生成

extern "C" __declspec(dllexport) void GetListItemData( HWND hListWnd, long index, char *outputResult )

您只需要一个 C++ 源文件,没有头文件,并编译为 DLL(在项目设置中)。除了函数和您需要的任何包含之外,您不需要任何代码。

在 C# 中

[System.Runtime.InteropServices.DllImport(
DLLPath,
CallingConvention = CallingConvention.Cdecl
)]
private static extern void GetListItemData(
System.IntPtr hWnd,
System.Int32 index,
[MarshalAs(UnmanagedType.LPArray)]byte[] buffer
);

不幸的是,您需要确保缓冲区有足够的大小。

关于c# - 在 C# 中为 p/invoke 创建一个基本的 C++ .dll,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4679858/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com