vsnprintf и snprintf, из-за которых dll не загружается

#c# #c #.net #gcc #printf

#c# #c #.net #gcc #printf

Вопрос:

Я боролся с этим в течение нескольких дней. У меня есть проект Visual Studio .net, написанный на C #, которому необходимо загрузить dll, написанную на C, с использованием компиляторов gcc в IDE Codeblocks.

DLL можно загрузить и использовать нормально, но когда я использую vsnprintf в dll, проект .net сообщает «Не удается загрузить DLL. Не удалось найти указанный модуль.» всякий раз, когда я пытаюсь вызвать функцию из dll.

Соответствующий код C #:

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;

namespace Scratchpad
{
    public partial class frmMain : Form
    {
        [DllImport("testpielibs", CallingConvention = CallingConvention.Cdecl)]
        static extern void SomeFunction(string a);    

        private void button3_Click(object sender, EventArgs e)
        {
            SomeFunction("ABC");
        }
    }
}
  

Соответствующий код C (DLL):

 #include <stdio.h>
#include <stdarg.h>

#define DLL_EXPORT __declspec(dllexport)

void DLL_EXPORT SomeFunction(const LPCSTR sometext)
{
    MessageBoxA(0, sometext, "DLL Message", MB_OK | MB_ICONINFORMATION);
}

DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            break;
        case DLL_PROCESS_DETACH:
            break;
        case DLL_THREAD_ATTACH:
            break;
        case DLL_THREAD_DETACH:
            break;
    }
    return TRUE;
}

int  log_printf(char *format, ...)
{
    char msg[256];
    va_list ap;

    memset(msg, 0, sizeof msg);
    va_start(ap, format);
    vsnprintf(msg, 256, format, ap);
    va_end(ap);
    return 0;
}
  

Обратите внимание, что «someFunction» даже не вызывает «log_printf». Проект все равно отлично строится, и когда я закомментирую строку с помощью vsnprintf, она работает так, как и должна с .net project, но именно эта строка является причиной того, что dll не может загружаться в .net project.

Если это имеет значение, вот мои библиотеки компоновщика для dll:

 ws2_32
iphlpapi
mswsock
winmm
user32
  

Кроме того, я чувствую, что было бы важно отметить, что на днях, как раз перед тем, как все это произошло, я получил сообщение об ошибке от codeblocks, в котором говорилось что-то о повреждении моего файла конфигурации. До этого этот проект создавался нормально, но мне пришлось вернуться и вручную переназначить настройки компилятора и компоновщика.

Есть предложения?

ОБНОВЛЕНИЕ: snprintf вызывает ту же проблему. Я могу использовать sprintf и vsprintf, но snprintf и vsnprintf приводят к тому, что dll не загружается в проект C #, даже если dll все равно будет собрана без ошибок или предупреждений. Я изучил соглашения о вызовах, используемые для импорта моих функций dll в мой проект c #, и Cdecl кажется подходящим вариантом, поскольку в нем конкретно сказано, что он «позволяет вызывать функции с помощью varargs, что делает его подходящим для методов, которые принимают переменное количество параметров, таких как Printf». Я также пытался импортировать someFunction, используя соглашения о вызовах Winapi, StdCall и ThisCall, но все они дают одинаковые результаты. Любая помощь была бы очень признательна, я некоторое время был в тупике по этому поводу.

Комментарии:

1. Привет, я подозреваю, что ваше утверждение «это может быть важно» таково, важно. Можете ли вы получить версию до повреждения? Если нет, я думаю, вам нужно опубликовать информацию, связанную со сборкой DLL.

2. Это была версия 16.01. Это все та же версия.

3. Это совершенно нормальная ошибка, специфичность для vsnprintf значительно усложняет объяснение. Код, скомпилированный с помощью GCC, зависит не только от перечисленных вами библиотек DLL операционной системы, но и от библиотеки времени выполнения C. Если это не может быть найдено во время выполнения, тогда это sayonara с этим исключением. memset() также является функцией времени выполнения C, но обычно генерируется как встроенная, поэтому не требует библиотеки. Просто используйте обычные стратегии устранения неполадок, включите привязки загрузчика или используйте Process Monitor от SysInternals для диагностики проблем с разрешением DLL.