2013-10-28 45 views
2

我tyring将C#字符串传递给C dll函数,它假设加密它。不幸的是,它根本就没有。调用该函数后,该字符串仍然相同。调用c改变传递参数在C中的dll函数#

C函数:

#include <stdio.h> 
    #include <stdlib.h> 
    extern "C"{ 
    __declspec(dllexport) void Encrypt(char *plainText,long height,long inputLength) 
    { 
     unsigned char *encryptedText=(unsigned char*)malloc(sizeof(plainText)); 
     unsigned char **cipherArray; 


     cipherArray=(unsigned char**)malloc(height*sizeof(unsigned char *)); 
     for(long i=0; i<height; i++) 
     { 
      cipherArray[i]=(unsigned char*)malloc(inputLength*sizeof(char)); 
      for (long j=0; j<inputLength ; j++) 
       cipherArray[i][j]='#'; 
     } 






     bool addRow=true; 
     long row=0; 
     long column = 0; 
     long arrayIterator = 0; 
     while(arrayIterator<inputLength){ 
      cipherArray[row][column] = plainText[arrayIterator]; 

        column++; 
        if(addRow)row++; 
        else row--; 
        if (row >= height) 
        { 
         row--; 
         row--; 
         addRow=false; 
        } 
        else if (row < 0) 
        { 
         row++; 
         row++; 
         addRow = true; 
        } 
        arrayIterator++; 
     } 



     long iterator=0; 
     for (long i=0; i< height; i++) 
      for(long j=0; j<inputLength;j++){ 
       if(cipherArray[i][j]!='#'){ 
        encryptedText[iterator]=cipherArray[i][j]; 
        iterator++; 
       } 
      } 

     long j=0; 
     while(j<inputLength){ 
      plainText[j]=encryptedText[j]; 
      printf("%c",encryptedText[j]); 
      j++; 
     } 

     for(long i=0; i<height; i++) 
      free(cipherArray[i]); 
     free(cipherArray); 
     cipherArray = NULL; 


    } 

    } 

含C#类:

namespace RailFenceCipher 
    { 
     public class CCipher 
     { 
      [DllImport("Win32Project3.dll", EntryPoint = "Encrypt", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] 
      public static extern void Encrypt([MarshalAs(UnmanagedType.LPStr)] string plainText, long height, long inputLength); 



     } 
    } 

,并呼吁功能:

 private void cipherC() 
      { 

       string plainText = this.fileInput; 
       Console.WriteLine("=== C# test, using IntPtr and Marshal ==="); 
       CCipher.dllprint(); 
       CCipher.Encrypt(plainText, this.height, this.fileInput.Length); 
       this.fileOutputC = plainText; 
       Console.WriteLine("=== END ==="); 
      } 
呼叫后

,明文没有改变。

+0

请注意,malloc(sizeof(plainText))只会分配4或8个字节(取决于您构建的是32位还是64位软件)。 – elgonzo

+0

继续了@elgonzo说的话,你可能想'malloc(strlen(plainText))' –

+0

@MarkkuK。不,它是malloc(inputLength) –

回答

2

这是可以预料的。你正在编组数据,但没有出。这是字符串类型参数的行为。您需要使用StringBuilder才能从本机代码中封送文本。

另外,C#long是64位,但C++ long在32位。您PInvoke的应该是:

[DllImport("Win32Project3.dll", CallingConvention = CallingConvention.Cdecl, 
    CharSet = CharSet.Ansi)] 
public static extern void Encrypt(StringBuilder plainText, 
    int height, int inputLength); 

而且你需要确保的是,StringBuilder实例您传递的容量足以要返回的文本。

也许更大的问题是你的C++代码被破坏了。至少,您需要修复接收sizeof(plainText)的malloc调用。这是一个指针的大小。您需要传递缓冲区的长度inputLength。在尝试互操作之前,您应该首先调试该代码。

+0

我发布了一个答案,大约是在你建议使用ref关键字的同时,而不是你指出的那样。你是否想详细说明为什么这种方法会失败? – Fopedush

+1

@Fopedush因为它映射到char **而不是char * –

+0

感谢您的答复。我用C代码放了一些printf调用。事实证明,它没有任何问题的C#字符串(在我发布的代码中实现)和heigth,但inputLength等于0.我试图用硬编码int调用函数(例如4),但它仍然等于0.任何建议? – sliwkacz