【问题标题】:BYTE * Array in C#C# 中的字节 * 数组
【发布时间】:2013-08-16 04:30:34
【问题描述】:

我正在尝试调用非托管函数。我从 C++ 调用它: 这是与我合作的测试项目

// ConsoleApplication5.cpp : main project file.

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <string>

using namespace System;

typedef int(*Funcs)(int, BYTE (*)[90], BYTE (*)[90]);

int main(array<System::String ^> ^args)
{
BYTE Input[] =
        {
                    0x7f,0x06,0x02,0x66,0xd2,0x3e,0x4c,0x7f,0x50,0x0a,0x5a,0x3c,0xab,0x43,0x5d,0x51,0x47,0xe5,0    x94,0x49,0xbd,0xef,0xc2,0xe4
,0x6c,0xb1,0x3b,0x3d,0x7c,0x47,0x65,0x8f,0x67,0xa6,0xe8,0x6a,0xe9,0x0e,0xbd,0x93,0xad,0x4a,    0x31,0x68,0x82,0x02,0xe6,0x7e,0x01,0x36,0xa,
9,0x75,0xf7,0xa0,0xb9,0xe9,0x1b,0x09,0xba,0x19,0x8c,0x97,0x18,0x9c,0xcc,0xd8,0x87,0x0e,0x04    ,0xb3,0x7c,0xc2,0xbf,0x1e,0x42,0x3e,0x8b,0x64,0xf5,0x60,0x43,0x96,0xe7,0xf6,0x7d,0x54,0x84,    0x54,0x00
        };
            BYTE OutPut[90];
Funcs Funcis;
HMODULE x = LoadLibrary(L"E:\\Games\\Silkroad\\HackShield\\ehsvc.dll");
Funcis = (Funcs)GetProcAddress(x,"16");
Funcis(13,&Input,&OutPut);

FILE * pFile;
pFile = fopen ("myfile.bin", "wb");
fwrite (OutPut , sizeof(char), sizeof(OutPut), pFile);
fclose (pFile);

Console::Read();
}

但是当我在 C# 中调用它时:

delegate int GetResponseD(int Code, byte[] Input, byte[] OutPut);
...
IntPtr hModule = LoadLibrary(@"###.dll");
IntPtr hFunc = GetProcAddress(hModule, "10");
GetResponseD Get = (GetResponseD)Marshal.GetDelegateForFunctionPointer(hFunc, typeof(GetResponseD));
GetResponse(13, Input, OutPut);

我只得到第一个字节

【问题讨论】:

  • 您是否尝试过在代理参数上使用适当的MarshaAs 属性?
  • 谁在C中分配这两个数组?来电者?
  • 从代码(13,&Input,&Output)来看,数组似乎必须由dll中的函数分配,对吧?
  • @xanatos 看起来数组应该由调用者分配,基于 C++ 示例中的 typedef 和调用。我们需要从C++代码中看到InputOutput的定义。

标签: c# unmanaged-memory


【解决方案1】:

类似的,如果数组是通过dll中的方法分配的:

// You will probably have to free in some way Input and Output
delegate int GetResponseD(int Code, ref IntPtr Input, ref IntPtr OutPut);

static void Main()
{
    IntPtr input = IntPtr.Zero, output = IntPtr.Zero;
    GetResponseD grd = null; // something

    int res = grd(1, out input, out output);

    var input2 = new byte[90];
    var output2 = new byte[90];

    Marshal.Copy(input, input2, 0, input2.Length);
    Marshal.Copy(output, output2, 0, output2.Length);

    // Remember that you have to free input and output!
}

在 C# 中,您不能使用非托管数组。您必须将他们的数据复制到托管数组中(不完全正确,但对于您的需要来说足够真实)

其他调用方式试试:

delegate int GetResponseD(int Code, ref IntPtr Input, ref IntPtr OutPut);

byte[] input = new byte[] {
    0x7f,0x06,0x02,0x66,0xd2,0x3e,0x4c,0x7f,0x50,0x0a,0x5a,0x3c,0xab,0x43,0x5d,0x51,0x47,0xe5,0x94,0x49,0xbd,0xef,0xc2,0xe4,0x6c,0xb1,0x3b,0x3d,0x7c,0x47,0x65,0x8f,0x67,0xa6,0xe8,0x6a,0xe9,0x0e,0xbd,0x93,0xad,0x4a,0x31,0x68,0x82,0x02,0xe6,0x7e,0x01,0x36,0xa,9,0x75,0xf7,0xa0,0xb9,0xe9,0x1b,0x09,0xba,0x19,0x8c,0x97,0x18,0x9c,0xcc,0xd8,0x87,0x0e,0x04,0xb3,0x7c,0xc2,0xbf,0x1e,0x42,0x3e,0x8b,0x64,0xf5,0x60,0x43,0x96,0xe7,0xf6,0x7d,0x54,0x84,0x54,0x00
};

byte[] output = new byte[90];

GetResponseD grd = null; // something

GCHandle h1 = GCHandle.Alloc(input, GCHandleType.Pinned);
GCHandle h2 = GCHandle.Alloc(output, GCHandleType.Pinned);

IntPtr p1 = h1.AddrOfPinnedObject();
IntPtr p2 = h2.AddrOfPinnedObject();

grd(13, ref p1, ref p2);

h1.Free();
h2.Free();

检查您的字节序列,我认为某处有一个,0 x94,而第三行开头的9 没有0x

据我所知,此方法有多种调用方式,第一个参数充当“开关”,其他两个参数根据第一个参数进行解释。

【讨论】:

  • @user2529018 我们在这里不是通灵者,发布一些完整的 C++ 使用代码示例。谁分配内存?然后如何访问输入和输出?谁释放内存?
  • 我没有 dll 的来源,但 dll 是 HackShield 的 ehsvc.dll
  • @user2529018 有没有问过dll的来源?我已经要求发布一些完整的 C++ 使用代码示例
猜你喜欢
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-01
  • 1970-01-01
  • 2013-01-26
相关资源
最近更新 更多