Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#中用于从DllImport函数检索引用的指针_C#_C++_Dll_Visual Studio 2005_Dllimport - Fatal编程技术网

C#中用于从DllImport函数检索引用的指针

C#中用于从DllImport函数检索引用的指针,c#,c++,dll,visual-studio-2005,dllimport,C#,C++,Dll,Visual Studio 2005,Dllimport,我在我的C#项目中引用了一个DLL,如下所示: [DllImport("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)] public static extern void FeeCalculation(string cin, string cout, string flimit, string f

我在我的C#项目中引用了一个DLL,如下所示:

[DllImport("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall,
           CharSet = CharSet.Ansi)]

        public static extern void FeeCalculation(string cin, string cout, string flimit,
            string frate, string fwindow, string fincrement, string fbird, 
            string fparameter, string fvalidation, string fcoupon);
FeeColution函数在DLL中导出如下:

extern "C" __declspec(dllexport) void __stdcall FeeCalculation(char *cin, 
char *cout, char *flimit, char *frate,
char *fwindow, char *fincrement, char *fbird,
char *fparameter, char *fvalidation, char *fcoupon);
< dll函数返回一个以char *形式引用的内部结构,因此如果您在C++中引用这个DLL,您将执行以下操作来计算并获得返回结构:

FeeCalculation(buff, (char *)&fans, (char *)fl, (char *)ft, (char *)fw, (char *)fi, (char *)fe, (char *)&fm, (char *)val, (char *)cpn);
现在,如何使用C#检索通过引用返回的值?也就是说,我如何在C#中执行相同的操作来获取返回的结构以获取返回的计算?我知道我需要创建一个不安全的方法,但是我不清楚如何处理C++中的内存地址,就像C++中的。 编辑:下面说明如何使用IntPtr,但如何将其放入相同的结构中,以便可以引用该结构的字段?

编辑:这是我感兴趣的返回结构(cout):

下面是我将与其他结构一起传递的(cin)(目前它们是零字节的,我想先让它工作,然后我将实现其余的):


本例中的char*参数不是字符串,而是指向表示数据的原始字节块的指针。您应该将参数封送为IntPtr类型的实例,并结合创建一块内存,然后将该内存块转换为可用的.NET类型

例如:

[StructLayout(LayoutKind.Sequential)]
struct MyUnmanagedType
{
    public int Foo;
    public char C;
}

IntPtr memory = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MyUnmanagedType)));

try
{
    FeeCalculation(memory);

    MyUnmanagedType result = (MyUnmanagedType)Marshal.PtrToStructure(
        memory, typeof(MyUnmanagedType));
}
finally
{
    Marshal.FreeHGlobal(memory);
}

要回答您的编辑,您需要创建一个结构,然后在字段上使用,以便使字节顺序和填充与原始dll相同。

编辑:现在我们有了可以使用的结构,更好的解决方案是可能的。只需在C++中声明与C++结构匹配的结构,并在ExtNestPrime

中使用它们
[StructLayout(LayoutKind.Sequential)]
public struct feeAnswer {
   public uint    fee;
   public uint    tax1;
   public uint    tax2;
   public uint    tax3;
   public uint    tax4;
   public uint    surcharge1;
   public uint    surcharge2;
   public uint    validationFee;
   public uint    couponFee1;
   public uint    couponFee2;
   public uint    couponFee3;
   public uint    couponFee4;
   public ushort  dstay;       //Day Stay
   public ushort  mstay;       //Minute Stay
   };

  [StructLayout(LayoutKind.Sequential, Pack=1)]
  public struct feeRequest {
   public byte   day;
   public byte   month;
   public uint   year;   //2000 ~ 2099
   public byte   hour;
   public byte   minute;
   public byte   rate;
   public byte   validation;
   public byte   coupon1;
   public byte   coupon2;
   public byte   coupon3;
   public byte   coupon4;
   };

  [DllImport ("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall,
             CharSet = CharSet.Ansi)]
  public static extern void FeeCalculation (
          feeRequest cin,
          out feeAnswer cout,
           ...



        ....
原始答案(在我们有结构之前)如下


在我看来,这些不是对内部字符串的引用,而是指向将由调用填充的字符串缓冲区的指针。如果返回的是字符串指针,那么这些指针将被声明为
char**
,而不是
char*

所以我认为这些只是标准的参数。只是有很多。因此,您的C#interop将如下所示

[DllImport("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall,
           CharSet = CharSet.Ansi)]
public static extern void FeeCalculation(string cin, 
        [MarshalAs(UnmanagedType.LPStr, SizeConst=100)]
        out string cout, 
        [MarshalAs(UnmanagedType.LPStr, SizeConst=100)]
        out string flimit,
或者,如果你的“字符串”不是真正的字符串

[DllImport("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall,
           CharSet = CharSet.Ansi)]
public static extern void FeeCalculation(string cin, 
        [MarshalAs(UnmanagedType.LPArray, SizeConst=100)]
        out byte[] cout, 
        [MarshalAs(UnmanagedType.LPArray, SizeConst=100)]
        out byte[] flimit,
        ....

即使函数需要更多的变量,您是否可以将其调用为FeeCalculation(memory)函数?为了示例起见,这只是一种简化。您需要在C#代码中重新声明每个非托管结构,然后分别封送每个非托管结构。啊,好吧,如果我想要cout和fm结果,我只需将其传递给PtrToStructure,就可以了。。基本上有两种说法?约翰的方法更容易了,因为我们有明确的结构来处理。在一般情况下,我的方法更可靠,但对于简单结构,John的方法更干净、更简单。他在问题陈述中说,它们不是真正的字符串。@MikeP:他还说它们是引用,它们显然不是。请原谅我的无知,但如果它们作为字节数组出现,然后我可以将其转换为我定义的结构,然后我还必须以字节数组的形式返回以获得我想要的响应?我的印象是他指的是按引用传递的概念,而不是按值传递。特别是C++和C语言引用。这意味着参数用于引用数据,而不附加API特定的含义。@MikeP:明白了。。这正是我所说的,因此,我们的参数你应该向我们展示你的结构,(至少其中一些)结构要好得多,我已经修改了我对FeeAccess结构的回答,你应该能够从那里概括。
[DllImport("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall,
           CharSet = CharSet.Ansi)]
public static extern void FeeCalculation(string cin, 
        [MarshalAs(UnmanagedType.LPStr, SizeConst=100)]
        out string cout, 
        [MarshalAs(UnmanagedType.LPStr, SizeConst=100)]
        out string flimit,
[DllImport("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall,
           CharSet = CharSet.Ansi)]
public static extern void FeeCalculation(string cin, 
        [MarshalAs(UnmanagedType.LPArray, SizeConst=100)]
        out byte[] cout, 
        [MarshalAs(UnmanagedType.LPArray, SizeConst=100)]
        out byte[] flimit,
        ....