我想将结构传递给 C 函数,并编写以下代码。
当我运行它时,第一个函数 -Foo1正在工作,然后函数Foo出现异常。你能帮我理解是什么问题吗?...
C代码:
typedef struct
{
int Size;
//char *Array;
}TTest;
__declspec(dllexport) void Foo(void *Test);
__declspec(dllexport) int Foo1();
void Foo(void *Test)
{
TTest *X = (TTest *)Test;
int i = X->Size;
/*for(int i=0;i<Test->Size;Test++)
{
Test->Array[i] = 127;
}*/
}
int Foo1()
{
return 10;
}
Run Code Online (Sandbox Code Playgroud)
C# 代码:
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
[StructLayout(LayoutKind.Sequential)]
public class TTest
{
public int Size;
}
class Program
{
[DllImport(@"C:\.net course\unmanaged1\unmanaged3\Debug\unmanaged3.dll", CharSet = CharSet.Auto)]
public static extern void Foo(
[MarshalAs(UnmanagedType.LPStruct)]
TTest lplf // characteristics
);
[DllImport(@"C:\.net course\unmanaged1\unmanaged3\Debug\unmanaged3.dll", CharSet = CharSet.Auto)]
public static extern int Foo1();
static void Main(string[] args)
{
TTest Test = new TTest();
Test.Size = 25;
int XX = Program.Foo1();
Program.Foo(Test);
}
}
}
Run Code Online (Sandbox Code Playgroud)
对于投票者:这个答案解决了两个问题:调用约定/MarhsalAs属性的直接问题,以及TTest如果他接受我的建议TTest变成结构体,他很快就会发现他的参数不起作用的问题。
您的本机代码要求一个void*,在 C# 中是一个IntPtr. 首先,您应该定义TTest为结构而不是类。其次,您应该将声明更改Foo为:
[DllImport(@"C:\.net course\unmanaged1\unmanaged3\Debug\unmanaged3.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public static extern void Foo(IntPtr lplf);
Run Code Online (Sandbox Code Playgroud)
第三,你应该固定TTestusingfixed关键字并将它的指针传递给Foo。如果您使用的是类,你可以使用Marhsal.StructureToPtr得到一个IntPtr从你的TTest。
这在两侧提供了相同的功能,可以传入指向任何类型的指针。您还可以使用要使用的所有类类型编写重载,因为它们都等同void*于本机端。对于结构体,您的参数将在前面加上ref.
我很好奇的是void*,TTest*当您在非托管代码中执行的第一件事被强制转换为TTest*. 如果您将参数切换为 a TTest*,则提供相同的功能会变得更简单。您的声明将变为:
[DllImport(@"C:\.net course\unmanaged1\unmanaged3\Debug\unmanaged3.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public static extern void Foo(ref TTest lplf);
Run Code Online (Sandbox Code Playgroud)
你会调用这个函数 Program.Foo(ref Test);
如果您使用的是类,ref则不需要,因为类是引用类型。
| 归档时间: |
|
| 查看次数: |
14053 次 |
| 最近记录: |