急。。。结构体传送问题

csdnadmin 2007-05-13 11:38:47
我用vc.net编写了一个dll,使用了一个结构体,其中有个量是数组,结构体采用指针传递模式,
在vb.net中调用dll的函数声明为byref传递结构体,调试发现vc收到的数据和要传送的不一致,好像变了。
哪位大虾对此比较明白,请指教
...全文
321 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
蒋晟 2007-05-14
  • 打赏
  • 举报
回复
写一个托管非托管混合DLL来做桥吧
真相重于对错 2007-05-14
  • 打赏
  • 举报
回复
调用函数
[C#]
public class App
{
public static void Main()
{
// array ByVal
int[] array1 = new int[ 10 ];
Console.WriteLine( "Integer array passed ByVal before call:" );
for( int i = 0; i < array1.Length; i++ )
{
array1[ i ] = i;
Console.Write( " " + array1[ i ] );
}
int sum1 = LibWrap.TestArrayOfInts( array1, array1.Length );
Console.WriteLine( "\nSum of elements:" + sum1 );
Console.WriteLine( "\nInteger array passed ByVal after call:" );

foreach( int i in array1 )
{
Console.Write( " " + i );
}

// array ByRef
int[] array2 = new int[ 10 ];
int size = array2.Length;
Console.WriteLine( "\n\nInteger array passed ByRef before call:" );
for( int i = 0; i < array2.Length; i++ )
{
array2[ i ] = i;
Console.Write( " " + array2[ i ] );
}
IntPtr buffer = Marshal.AllocCoTaskMem( Marshal.SizeOf( size )
* array2.Length );
Marshal.Copy( array2, 0, buffer, array2.Length );

int sum2 = LibWrap.TestRefArrayOfInts( ref buffer, ref size );
Console.WriteLine( "\nSum of elements:" + sum2 );
if( size > 0 )
{
int[] arrayRes = new int[ size ];
Marshal.Copy( buffer, arrayRes, 0, size );
Marshal.FreeCoTaskMem( buffer );
Console.WriteLine( "\nInteger array passed ByRef after call:" );
foreach( int i in arrayRes )
{
Console.Write( " " + i );
}
}
else
Console.WriteLine( "\nArray after call is empty" );

// matrix ByVal
const int DIM = 5;
int[,] matrix = new int[ DIM, DIM ];

Console.WriteLine( "\n\nMatrix before call:" );
for( int i = 0; i < DIM; i++ )
{
for( int j = 0; j < DIM; j++ )
{
matrix[ i, j ] = j;
Console.Write( " " + matrix[ i, j ] );
}
Console.WriteLine( "" );
}
int sum3 = LibWrap.TestMatrixOfInts( matrix, DIM );
Console.WriteLine( "\nSum of elements:" + sum3 );
Console.WriteLine( "\nMatrix after call:" );
for( int i = 0; i < DIM; i++ )
{
for( int j = 0; j < DIM; j++ )
{
Console.Write( " " + matrix[ i, j ] );
}
Console.WriteLine( "" );
}

// string array ByVal
String[] strArray = { "one", "two", "three", "four", "five" };
Console.WriteLine( "\n\nString array before call:" );
foreach( String s in strArray )
Console.Write( " "+ s );
int lenSum = LibWrap.TestArrayOfStrings( strArray, strArray.Length );
Console.WriteLine( "\nSum of string lengths:" + lenSum );
Console.WriteLine( "\nString array after call:" );
foreach( String s in strArray )
{
Console.Write( " " + s );
}

// struct array ByVal
MyPoint[] points = { new MyPoint(1,1), new MyPoint(2,2), new MyPoint(3,3) };
Console.WriteLine( "\n\nPoints array before call:" );
foreach( MyPoint p in points )
Console.WriteLine( "x = {0}, y = {1}", p.x, p.y );
int allSum = LibWrap.TestArrayOfStructs( points, points.Length );
Console.WriteLine( "\nSum of points:" + allSum );
Console.WriteLine( "\nPoints array after call:" );
foreach( MyPoint p in points )
Console.WriteLine( "x = {0}, y = {1}", p.x, p.y );

// struct with strings array ByVal
MyPerson[] persons = { new MyPerson( "Kim", "Akers" ),
new MyPerson( "Adam", "Barr" ), new MyPerson( "Jo", "Brown" )};

Console.WriteLine( "\n\nPersons array before call:" );
foreach( MyPerson pe in persons )
Console.WriteLine( "first = {0}, last = {1}", pe.first, pe.last );
int namesSum = LibWrap.TestArrayOfStructs2( persons, persons.Length );
Console.WriteLine( "\nSum of name lengths:" + namesSum );
Console.WriteLine( "\n\nPersons array after call:" );
foreach( MyPerson pe in persons )
Console.WriteLine( "first = {0}, last = {1}", pe.first, pe.last );
}
}


真相重于对错 2007-05-14
  • 打赏
  • 举报
回复
该示例说明如何传递以下类型的数组:
通过值传递的整数数组。
通过引用传递的整数数组,它可以调整大小。
通过值传递的多维整数数组(矩阵)。
通过值传递的字符串数组。
包含整数的结构数组。
包含字符串的结构数组。
除非数组是通过引用显式封送的,否则默认行为将该数组作为 In 参数进行封送处理。可以通过显式应用 InAttribute 和 OutAttribute 属性更改此行为。Microsoft .NET Framework SDK 在 Samples\Technologies\Interop\Platform-Invoke 中包括此示例的完整 Visual Basic .NET 和 C# 版本。

Arrays 示例使用以下非托管函数(这里同时显示其原始函数声明):

从 PinvokeLib.dll 导出的 TestArrayOfInts。
int TestArrayOfInts(int* pArray, int pSize);

从 PinvokeLib.dll 导出的 TestRefArrayOfInts。
int TestRefArrayOfInts(int** ppArray, int* pSize);

从 PinvokeLib.dll 导出的 TestMatrixOfInts。
int TestMatrixOfInts(int pMatrix[][COL_DIM], int row);

从 PinvokeLib.dll 导出的 TestArrayOfStrings。
int TestArrayOfStrings(char** ppStrArray, int size);

从 PinvokeLib.dll 导出的 TestArrayOfStructs。
int TestArrayOfStructs(MYPOINT* pPointArray, int size);

从 PinvokeLib.dll 导出的 TestArrayOfStructs2。
int TestArrayOfStructs2 (MYPERSON* pPersonArray, int size);

PinvokeLib.dll 是一个自定义非托管库,它包含前面列出的函数的实现和以下两个结构变量:MYPOINT 和 MYPERSON。这些结构包含以下元素:

typedef struct _MYPOINT
{
int x;
int y;
} MYPOINT;

typedef struct _MYPERSON
{
char* first;
char* last;
} MYPERSON;

在该示例中,MyPoint 和 MyPerson 结构包含嵌入类型。StructLayoutAttribute 属性经过设置,以确保成员在内存中按它们的出现顺序依次排列。

LibWrap 类包含一组由 App 类调用的方法。有关传递数组的特定详细信息,请参见以下示例中的注释。默认情况下,作为引用类型的数组被作为 In 参数进行传递。为使调用方接收结果,必须将 InAttribute 和 OutAttribute 显式应用于包含该数组的参数。

声明原型
[C#]
// Declares a managed structure for each unmanaged structure.
[ StructLayout( LayoutKind.Sequential )]
public struct MyPoint
{
public int x;
public int y;
public MyPoint( int x, int y )
{
this.x = x;
this.y = y;
}
}
[ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )]
public struct MyPerson
{
public String first;
public String last;
public MyPerson( String first, String last )
{
this.first = first;
this.last = last;
}
}

public class LibWrap
{
// Declares a managed prototype for an array of integers by value.
// The array size cannot be changed, but the array is copied back.
[ DllImport( "..\\LIB\\PinvokeLib.dll" )]
public static extern int TestArrayOfInts([In, Out] int[] array, int size );

// Declares a managed prototype for an array of integers by reference.
// The array size can change, but the array is not copied back
// automatically because the marshaler does not know the resulting size.
// The copy must be performed manually.
[ DllImport( "..\\LIB\\PinvokeLib.dll" )]
public static extern int TestRefArrayOfInts( ref IntPtr array,
ref int size );

// Declares a managed prototype for a matrix of integers by value.
[ DllImport( "..\\LIB\\PinvokeLib.dll" )]
public static extern int TestMatrixOfInts([In, Out] int[,] pMatrix,
int row );
// Declares a managed prototype for an array of strings by value.
[ DllImport( "..\\LIB\\PinvokeLib.dll" )]
public static extern int TestArrayOfStrings( [In, Out]
String[] stringArray, int size );

// Declares a managed prototype for an array of structures with integers.
[ DllImport( "..\\LIB\\PinvokeLib.dll" )]
public static extern int TestArrayOfStructs([In, Out] MyPoint[]
pointArray, int size );

// Declares a managed prototype for an array of structures with strings.
[ DllImport( "..\\LIB\\PinvokeLib.dll" )]
public static extern int TestArrayOfStructs2( [In, Out]
MyPerson[] personArray, int size );
}

csdnadmin 2007-05-14
  • 打赏
  • 举报
回复
非常感谢大家,但还没解决,都忙了快2天了

可能我说的不太明白,再详细说明一下
我调式vc。net的时候发现收到的结构体中的BlockID,SecID,CardID完全正常,但是
KeyB内容中的数值不对,执行后在vb中可以看到b和a中的竟然完全一样。

下面是相关的代码
------------------------------------------------------------------
vc.net中的代码

typedef struct _CARD
{ unsigned char BlockID;
unsigned char SecID;
unsigned char KeyB[6];
unsigned char CardID;

} CARD,* p_CARD;

MI_CARD_API long WINAPI IssueUserCard(p_CARD user_card,unsigned long * CardSN,p_CARD user_card1)
{
memcpy(user_card1,user_card,9);
}
-------------------------------------------------------------------
vb中的代码
Public Declare Auto Function IssueUser Lib "test" (ByRef UCardStructure As CARD,ByRef aa As CARD) As Integer '发行用户
Public Structure CARD
Public BlockID As Byte
Public SecID As Byte
Public key() As Byte
Public CardID As Byte
End Structure
Private Sub Button15_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button15.Click
dim a,b as card
dim i as integer
redim a.key(6)
redim b.key(6)
a.BlockID =1
a.SecID =2
for i=0 to 5
a.key(i)=i+3
next i
a.CardID=9
i=IssueUserCard(a,b)
End Sub

zhangliu_521 2007-05-13
  • 打赏
  • 举报
回复
http://topic.csdn.net/t/20050314/19/3850315.html
masterz 2007-05-13
  • 打赏
  • 举报
回复
可能是内存对齐方式的不同,试试用在定义结构之前加上
#pragma pack(4)

7,540

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 VC.NET
社区管理员
  • VC.NET社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧