2009-03-29 5 views
1

Это моя 3-я проблема, связанная с проблемой blowfish в C#. Несмотря на то, что я не мог использовать blowfish в моем приложении, я решил использовать его как внешнюю dll C++. Обратите внимание, что я пробовал Blowfish.NET и любой другой, проблема в том, что я переводил код с C++ на C#, а код C# должен делать то же самое, что и код C++.Проблема при вызове функции dll C++ из C#

До сих пор:

--->C++ DLL source<---

Примечание экспортируемые функции в конце кода

C# код (определение)

[DllImport("TestDLL.dll", EntryPoint = "Initkey" ,ExactSpelling = true , CallingConvention = CallingConvention.Cdecl)] 
    public static unsafe extern void Initkey(byte[] key); 

    [DllImport("TestDLL.dll", EntryPoint = "encode", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] 
    public static unsafe extern void encode(UInt32 *stream); 

C# код (функция вызова)

-Initialize Blowfish ключ

UInt32[] keyarray = new UInt32[2]; 
//some code 
Extern.Initkey(Misc.ConvertFromUInt32Array(keyarray)); 
// 
// 
//Helper function used to convert a UInt32 array into Byte array. 
public static byte[] ConvertFromUInt32Array(UInt32[] array) 
{ 
    List<byte> results = new List<byte>(); 
    foreach (UInt32 value in array) 
    { 
     byte[] converted = BitConverter.GetBytes(value); 
     results.AddRange(converted); 
    } 
    return results.ToArray(); 
} 

-Encode данных.

  UInt32[] keyarray2 = new UInt32[2]; 
      //some code 
      unsafe 
      { 
       fixed (UInt32* LPBYTE = keyarray2) 
       { 
        Extern.encode(LPBYTE); 
       } 
      } 

После keyarray2 перезаписаны функцией Encode, я проверить значения в коде C++ путем дешифрования их, чтобы убедиться, что все в порядке.

Ну, это нехорошо. Это моя проблема. Вот почему я прошу вас о вашей помощи.

Значения различаются при их расшифровке, но если я их зашифровываю и расшифровываю их в источнике C++, они равны. Код C++ абсолютно одинаковый, за исключением того, что нет библиотеки DLL, поскольку код находится на C++.

Может быть, из-за функции Initialize.I прочитал пару месяцев назад, что массивы в C++ передаются как Pointers.I не верю, но даже в этом - может быть, это проблема?

Я не могу найти ключ. Я потратил всю свою жизнь на эту муху в C#. По крайней мере, это решение должно работать, но это не так. Почему?

+1

Вы потратили впустую свою жену? Немного о переоценке IMO .. – Blorgbeard

ответ

1

Чтобы добавить к сказанному jachymko, также проверьте документацию для BitConverter - вы должны быть уверены, что передаете ключ и данные в указанном порядке байтов. Замечание - из вашего предыдущего потока я успешно зашифровал данные, используя модифицированный шифр Blowfish.NET, и получил его в соответствии с результатом вашего кода на C++.

+0

@ Дэйв, Спасибо за помощь! Пожалуйста, не могли бы вы загрузить источник модифицированного Blowfish.NET. –

+0

Да, я загружу источник где-нибудь. Это был проект C# 2008 и проект C++ 2008 - они оба дают для меня одинаковый результат. –

+0

@ Dave, спасибо! Пожалуйста, вставьте ссылку здесь, а не в мою старую нить. Вы используете мое шифрование с помощью Clow blowfish, а не какое-то другое? –

0

Массивы в C и C++ передаются как указатели. Семантика для массивов в C# включает дополнительный слой косвенности. Ваша программа на C# (возможно) передает адрес переменной, которая содержит адрес данных.

Недавно я боролся с передачей массива байтов от C# к функции C и должен был маршалировать данные в обоих направлениях. Для меня не очевидно, что ваш код это делает.

Лучше, чем объяснение, я приведу конкретный пример:

//extern "C" LIBEXIFWRAPPER_API void findEXIFtagValue(void * load, unsigned int tagID, char* buf, int bufLen); 
[DllImport("libexif-wrapper.dll")] 
unsafe public static extern IntPtr findEXIFtagValue([MarshalAs(UnmanagedType.SysUInt)]IntPtr load, int tagID, [MarshalAs(UnmanagedType.SysUInt)]IntPtr buf, int bufLen); 

Эта функция принимает указатель на непрозрачные данные, в междунар и байтовый массив, в котором он хранит текстовую строку.

Следующий фрагмент показывает, как объявляется массив, переданный функции C и экстрагируют результаты:

const int tagBuffer = 1024; 
IntPtr buf = Marshal.AllocHGlobal(tagBuffer); 

findEXIFtagValue(loader, (int)ExifTag.EXIF_TAG_DATE_TIME, buf, tagBuffer); 
string s = Marshal.PtrToStringAnsi(buf); 

Обратите внимание, что аргумент маршалируется в прототипе и маршалируются еще раз, чтобы получить результат.

Все это не было особенно очевидно для меня. Кажется, что IntPtr является эквивалентом C# для void *, за исключением того, что мне пришлось использовать SysUInt для управления (C) void *. Указатель на массив байтов маршалируется как SysUInt.

(от C# нуб)

НТН

0

Может быть, вы должны попробовать использовать ref для указателей и out для функций, которые возвращают данные через аргумент. Дай мне знать, если это работает. Благодарю.

1

Знаете ли вы, что вы инициализируете временный экземпляр, который был разрушен к моменту возвращения функции Initkey? Вы должны объединить все это в одну функцию или создать cBlowfish в куче и вернуть указатель на код C# (он может рассматривать его как непрозрачный IntPtr).

Кроме того, здесь не нужно использовать небезопасные меры. Просто передайте UInt32 [] напрямую.

Смежные вопросы