使用struct'作为参数从C#调用C函数。 [英] Calling a C function from C# with struct' as a parameter.

查看:91
本文介绍了使用struct'作为参数从C#调用C函数。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述




作为C#的新手并且一直使用C语言,我陷入困境

并且存在互操作问题。


我有一个DLL导出某些功能(并用C语言编写)。

1这样的功能的签名如下:


externC

{

__declspec(dllexport)int EnumerateDevice(DEVICE ** DeviceList);

}


struct DEVICE

{

int DeviceNo;

DEVICE * next;

};


我需要从我的C#代码中调用这个函数。我怎么去做这个?b $ b这个?我浏览了一些互操作示例,但大多数都使用基本的

数据类型(int和char)作为示例中的参数。


此处的任何代码示例这将是有用的。


提前致谢。


问候,

Treadstone

解决方案

" Treadstone" < u。******* @ gmail.comschrieb im Newsbeitrag

news:11 ********************** @ o80g2000hse.googlegr oups.com ...





成为C#的新手,并与C合作过一路上,我被卡住了,因为互操作问题,我被困了。


我有一个DLL导出某些功能(并用C语言编写)。

1这样的功能的签名如下:



你知道这个链接:
http://www.pinvoke.net


它不包含你的方法,但有一些例子,编组

结构巫婆P / Invoke。


HTH

Christof


Treadstone,


首先,您必须定义结构:


[StructLayout(LayoutKind.Sequential)]

public struct设备

{

public int DeviceNo;

public IntPtr Next;

}


你使用IntPtr作为Next参数因为你要

在需要时手动编组。然后,你定义你的API如下:


[DllImport(" dllname.dll")]

static int EnumerateDevice(ref IntPtr DeviceList);


然后你会调用api将IntPtr传递给你的方法。当你将
取回时,你会调用Marshal

类上的静态PtrToStructure方法来获取Device结构的实例。您还需要

来为列表中的下一个项目执行此操作,如结构中的下一个字段所指示的那样。


最后,您可能必须释放由

分配的内存,调用EnumerateDevice,以及每个$ / b $ b $字段指向的所有项目。枚举中的结构。

-

- Nicholas Paldino [.NET / C#MVP]

- mv*@spam.guard.caspershouse.com


" Treadstone" < u。******* @ gmail.com写信息

新闻:11 ********************** @ o80g2000hse.googlegr oups.com ...





成为C#的新手,并与C合作过一路上,我被卡住了,因为互操作问题,我被困了。


我有一个DLL导出某些功能(并用C语言编写)。

1这样的功能的签名如下:


externC

{

__declspec( dllexport)int EnumerateDevice(DEVICE ** DeviceList);

}


struct DEVICE

{

int DeviceNo;

DEVICE * next;

};


我需要从我的C#代码中调用此函数。我怎么去做这个?b $ b这个?我浏览了一些互操作示例,但大多数都使用基本的

数据类型(int和char)作为示例中的参数。


此处的任何代码示例这将是有用的。


提前致谢。


问候,

Treadstone


Nicholas,


我按照你建议的方式定义了结构,以及

DllImport声明。

然而,当我打电话给Marshal.AllocCoTaskMem或

Marshal.AllocHGlobal或Marshal.PtrToStructure时,我得到了一个

系统.NotSupported exception。


我的函数里面的代码如下:


//开始代码链接

IntPtr DeviceList = IntPtr.Zero;

DEVICE device = new DEVICE(); // DEVICE结构已定义

已经。


Marshal.AllocHGlobal(Marshal.SizeOf(device); //这给了我一个
System.NotSupportedException


//我的函数调用

iReturnValue = EnumerateDevice(ref DeviceList);


Marshal.PtrToStructure(DeviceList,device)//如果我没有调用

Marshal.AllocHGlobal调用,那么

//
$ b这里发生了$ b System.NotSupportedException。


//代码片段结束


我尝试了Marshal.PtrToStructure与所有可能的组合

重载的方法,但最终结果相同。

我在调用Marshal的方法时犯了一些错误(例如

AllocHGlobal / AllocCoTaskMem / PtrToStrucuture)?或者它与VS2005的版本有什么关系?


先谢谢。


Christof:感谢指向网站的指针。这对我来说很有帮助。


问候,

Treadstone


Hi,

Being a newbie to C# and having worked with C all the way, I am stuck
with an interop problem.

I have a DLL exporting certain functions (and written in C).
The signature of 1 such function is as follows:

extern "C"
{
__declspec(dllexport) int EnumerateDevice(DEVICE **DeviceList);
}

struct DEVICE
{
int DeviceNo;
DEVICE *next;
};

I need to call this function from my C# code. How do I go about doing
this? I went through some interop samples but most of them use basic
data types (int and char) as parameters in their examples.

Any code sample in this regard would be useful.

Thanks in advance.

Regards,
Treadstone

解决方案

"Treadstone" <u.*******@gmail.comschrieb im Newsbeitrag
news:11**********************@o80g2000hse.googlegr oups.com...

Hi,

Being a newbie to C# and having worked with C all the way, I am stuck
with an interop problem.

I have a DLL exporting certain functions (and written in C).
The signature of 1 such function is as follows:

Do you know this link:
http://www.pinvoke.net

It doesn''t contain your method, but has some examples, of Marshalling
structs witch P/Invoke.

HTH
Christof


Treadstone,

First, you are going to have to define the structure:

[StructLayout(LayoutKind.Sequential)]
public struct Device
{
public int DeviceNo;
public IntPtr Next;
}

You use an IntPtr for the Next parameter because you are going to
marshal it manually when you need it. Then, you define your API like this:

[DllImport("dllname.dll")]
static int EnumerateDevice(ref IntPtr DeviceList);

You would then call the api passing an IntPtr to your method. When you
get it back, you would call the static PtrToStructure method on the Marshal
class to get an instance of the Device structure back. You would also need
to do this for next item in the list, as pointed out by the Next field on
the structure.

Finally, you will probably have to deallocate the memory allocated by
the call to EnumerateDevice, as well as all the items pointed to by the Next
field in each of the structures in the enumeration.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Treadstone" <u.*******@gmail.comwrote in message
news:11**********************@o80g2000hse.googlegr oups.com...

Hi,

Being a newbie to C# and having worked with C all the way, I am stuck
with an interop problem.

I have a DLL exporting certain functions (and written in C).
The signature of 1 such function is as follows:

extern "C"
{
__declspec(dllexport) int EnumerateDevice(DEVICE **DeviceList);
}

struct DEVICE
{
int DeviceNo;
DEVICE *next;
};

I need to call this function from my C# code. How do I go about doing
this? I went through some interop samples but most of them use basic
data types (int and char) as parameters in their examples.

Any code sample in this regard would be useful.

Thanks in advance.

Regards,
Treadstone


Nicholas,

I defined the structure in the manner suggested by you, along with the
DllImport declaration.
However, the moment I called either Marshal.AllocCoTaskMem or
Marshal.AllocHGlobal or Marshal.PtrToStructure, I am getting a
System.NotSupported exception.

My code inside my function is as follows:

//BEGINNING OF CODE SNIPPET

IntPtr DeviceList = IntPtr.Zero;
DEVICE device = new DEVICE( ); //The DEVICE structure has been defined
already.

Marshal.AllocHGlobal(Marshal.SizeOf(device); //This gives me a
System.NotSupportedException

//My function call
iReturnValue = EnumerateDevice(ref DeviceList);

Marshal.PtrToStructure(DeviceList, device) //If I do not invoke the
Marshal.AllocHGlobal call, then
the //
System.NotSupportedException occurs here.

//END OF CODE SNIPPET

I tried the Marshal.PtrToStructure with all possible combinations of
the overloaded methods, but ended up with the same result.
Am I making some mistake while calling the methods of Marshal (such as
AllocHGlobal/ AllocCoTaskMem/PtrToStrucuture)? Or does it have
something to do with the version of VS2005?

Thanks in Advance.

Christof: Thanks for the pointer to the website. It has been of great
help to me.

Regards,
Treadstone


这篇关于使用struct'作为参数从C#调用C函数。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆