C#アプリケーションでC言語で書かれた関数を使いたい。関数は dll ファイルにエクスポートされます。C 関数コード:
#include <stdio.h>
#include <stdlib.h>
extern "C" __declspec(dllexport) char * Encrypt(char plainText[],int height,long inputLength)
{
char *encryptedText=(char*)malloc(sizeof(plainText));
char **cipherArray;
cipherArray=(char**)malloc(height*sizeof(char *));
for(long i=0; i<height; i++)
{
cipherArray[i]=(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++;
}
}
for(int i=0; i<height; i++)
free(cipherArray[i]);
free(cipherArray);
cipherArray = NULL;
return encryptedText;
}
C# アプリでは、この関数を使用するクラスを作成しました。
namespace RailFenceCipher
{
public class CCipher
{
[DllImport("CCipher.dll", CharSet = CharSet.Unicode)]
unsafe public static extern char* Encrypt(char[] plainText, int height, long inputLength);
}
}
ここが難しいところです... C 関数は char* オブジェクト (char 配列) を返します。私の質問は、関数の結果を C# 文字列に割り当てるにはどうすればよいですか?
今まで自力でなんとかしようとしていたのですが、うまくいきません...
dll 関数を呼び出します。
private void cipherC()
{
this.fileOutputC = "";
unsafe
{
string cEncrypted = new string(((CCipher.Encrypt(this.fileInput.ToCharArray(), this.height,fileInput.Length))));
this.fileOutputC = cEncrypted;
}
}
事前に助けてくれてありがとう!
編集:
コードを次のように再編成しました。
dll の C コード:
struct Wrapper{
unsigned char* plainText;
int height;
long inputLength;
unsigned char* result;
};
void Encrypt(unsigned char plainText[],int height,long inputLength,unsigned char result[])
{
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){
result[j]=encryptedText[j];
j++;
}
for(long i=0; i<height; i++)
free(cipherArray[i]);
free(cipherArray);
cipherArray = NULL;
}
extern "C" __declspec(dllexport) void CreateCWrapper(struct Wrapper **myWrapper,string plainText, long height, string result,long inputLength){
*myWrapper=(struct Wrapper*)malloc(sizeof(struct Wrapper));
(*myWrapper)->height = height;
(*myWrapper)->inputLength= inputLength;
(*myWrapper)->plainText= (unsigned char*)malloc(inputLength * sizeof(char));
if ((*myWrapper)->plainText != NULL)
for (long i = 0; i < inputLength; ++i)
(*myWrapper)->plainText[i] = plainText[i];
(*myWrapper)->result= (unsigned char*)malloc(inputLength * sizeof(char));
}
extern "C" __declspec(dllexport) void EncryptWithWrapper(Wrapper *myWrapper){
unsigned char *table=(unsigned char*)malloc(sizeof(char)*myWrapper->inputLength);
for(long i=0;i<myWrapper->inputLength;i++){
table[i]=myWrapper->plainText[i];
}
unsigned char *res=(unsigned char*)malloc(sizeof(char)*myWrapper->inputLength);
Encrypt(table,myWrapper->height,myWrapper->inputLength,res);
for(long i=0;i<myWrapper->inputLength;i++){
myWrapper->result[i]=res[i];
}
free(table);
free(res);
}
extern "C" __declspec(dllexport) string getStrResultFromWrapper(Wrapper *myWrapper){
string stringres;
for(long i=0;i<myWrapper->inputLength;i++){
stringres+=myWrapper->result[i];
}
return stringres;
}
C# クラス:
public class CCipher
{
[StructLayout(LayoutKind.Sequential)]
public struct Wrapper
{
public IntPtr plainText;
public int height;
public IntPtr inputLength;
public string result;
}
[DllImport("CCipher.dll")]
public static extern void CreateCWrapper(out IntPtr myWrapper, string plainText, long height, string result, long inputLength);
[DllImport("CCipher.dll")]
public static extern void EncryptWithWrapper(IntPtr myWrapper);
[DllImport("CCipher.dll")]
public static extern string getStrResultFromWrapper(IntPtr myWrapper);
}
および呼び出し関数:
private void cipherC()
{
IntPtr myWrapper;
CCipher.CreateCWrapper(out myWrapper, this.fileInput, this.height, this.fileOutputC, this.fileInput.Length);
CCipher.EncryptWithWrapper(myWrapper);
CCipher.Wrapper dataWrapper=(CCipher.Wrapper) Marshal.PtrToStructure(myWrapper,typeof(CCipher.Wrapper));
}
問題は、次の呼び出し時です。
CCipher.CreateCWrapper(out myWrapper, this.fileInput, this.height, this.fileOutputC, this.fileInput.Length);
アプリが停止するだけです。ヒントはありますか?