На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
> Использование DLL в проекте C#WPF , DLL-ка на Си
    Уважаемые форумчане , помогите с вопросом по использованию функций DLL(написана на Си) ,
    проект очень простенький все на одной кнопочке и пару текстЕдитов
    весь код линейный в одной кнопке
    MainWindow.xaml.cs
    Скрытый текст

    ExpandedWrap disabled
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      using System.Windows;
      using System.Windows.Controls;
      using System.Windows.Data;
      using System.Windows.Documents;
      using System.Windows.Input;
      using System.Windows.Media;
      using System.Windows.Media.Imaging;
      using System.Windows.Navigation;
      using System.Windows.Shapes;
       
      using System.Reflection;
       
      using System.Runtime.InteropServices;
       
      namespace ComHyTech
      {
       
       
          public partial class MainWindow : Window
          {
       
       
       
              public MainWindow()
              {
                  InitializeComponent();
              }
       
              struct hcSqlParmT
              {
                  public ushort size;
              };
       
              [StructLayout(LayoutKind.Sequential)]
              unsafe struct hcSqlDstInfoT     // Структура "Информация о колонках результата"
              {
                  public int aliasno;
                  public int fieldno;
                  public int type;
                  public uint len;
                  public uint off;
                  public fixed char coder[32];
                  public fixed char fname[32];
                  public int func;
                  public fixed char asname[32];
                  public int key;
                  public int resno;
              };
          
              [DllImport("hscli.dll")]
              static extern int hcSqlInit(IntPtr dummy);
       
              [DllImport("hscli.dll")]
              static extern int hcSqlCheckInit();
              
              [DllImport("hscli.dll")]
              static unsafe extern int hcSqlAllocConnect(out int pdb);
              //static unsafe extern int hcSqlAllocConnect(int* pdb);
       
              [DllImport("hscli.dll")]
              static unsafe extern int hcSqlConnect(int pdb, string server, string login , string password);
       
              [DllImport("hscli.dll")]                        
              static unsafe extern int hcSqlAllocStmt(int pdb, int * pOper);// Создать оператор
       
              [DllImport("hscli.dll")]
              static unsafe extern int hcSqlSetStmtAttr(int pOper, uint option, void* pValue, uint size);
       
              [DllImport("hscli.dll")]
              static unsafe extern int hcSqlExecDirect(int pOper, string strSQL);// Выполняем SQLзапрос
       
       
              [DllImport("hscli.dll")]
              static unsafe extern int hcSqlNumResultCols(int pOper, int*  pCol);
       
              [DllImport("hscli.dll")]
              static unsafe extern int hcSqlRowCount(int pOper, long* pStr);
       
              [DllImport("hscli.dll")]
              static unsafe extern int hcSqlOpenResults(int pOper, uint *pRecSize);
              
              [DllImport("hscli.dll")]
              static unsafe extern int hcSqlGetStmtAttr(int pOper, uint option, int pos, hcSqlDstInfoT[] pValue, uint size, uint* cnt);
       
              [DllImport("hscli.dll")]
              static unsafe extern int hcSqlReadResults(int pOper, long gStart, byte[] pBuf, uint wBufSize, uint * cnt);
              
       
              [DllImport("hscli.dll")]
              static unsafe extern int hcSqlCloseResults(int pOper); // Закрытие доступа к результатам
              [DllImport("hscli.dll")]
              static unsafe extern int hcSqlFreeConnect(int pdb); // Освободить соединение
              [DllImport("hscli.dll")]
              static unsafe extern int hcSqlDone();// Завершение работы
       
              private unsafe void button_Click(object sender, RoutedEventArgs e)
              {
                  int err = -300000;// код ошибки заведомо не существующий
                  
                  int       pdb = 0 ;
                  int     pOper = 0 ; // идетификатор оператора
                  int      pCol = 0 ; // кол-во колонок
                  long     pStr = 0 ; // кол-во строк
                  uint pRecSize = 0 ; // размер записи
                  uint    cntOp = 0 ; //  сколько байтов записали в буфер
       
                  long   gStart = 0 ; // с какой записи начинаем читать
       
                  if ((err = hcSqlInit(IntPtr.Zero)) != 0)  { return; } // Инициализация клиентской части
                  
                  textBox_Copy3.AppendText("Инициализация клиентской части err = " + err.ToString() + "\r\n");
       
                  err = hcSqlCheckInit();                  // Проверка завершения инициализации
                  
                  textBox_Copy3.AppendText("Проверка завершения инициализации err = " + err.ToString() + "\r\n") ;
       
                  unsafe
                  {
                      err = hcSqlAllocConnect  (out pdb ) ;           //  Создать соединение
                      textBox_Copy3.AppendText ("Создать соединение err = " + err.ToString() + "\r\n" );
                      textBox_Copy3.AppendText ("соединение         pdb = " + pdb.ToString() + "\r\n" );
                      err = hcSqlConnect       (pdb, textBox.Text.ToString() , textBox1.Text.ToString(), textBox2.Text.ToString()); //Установить связь с СУБД
                      textBox_Copy3.AppendText ("Установить связь с СУБД err = " + err.ToString() + "\r\n");
                      err = hcSqlAllocStmt     (pdb,   &pOper                                         ); // Создать оператор
                      textBox_Copy3.AppendText ("Создать оператор err = " + err.ToString()   + "\r\n" );
                      textBox_Copy3.AppendText ("оператор       pOper = " + pOper.ToString() + "\r\n" );
                      err = hcSqlSetStmtAttr   (pOper,  1001,   (void*)1,   0                         ); // ф-ция "Изменение параметров оператора"
                      textBox_Copy3.AppendText ("ф-ция  Изменение параметров оператора  err = " + pOper.ToString() + "\r\n");
                      err = hcSqlExecDirect    (pOper, textBox3.Text.ToString()                       ); // Выполняем SQLзапрос
                      textBox_Copy3.AppendText ("Выполняем SQLзапрос = " + pOper.ToString() + "\r\n"  );
       
                      err = hcSqlNumResultCols (pOper, &pCol);     // Получить кол-во колонок результата
                      textBox_Copy3.AppendText("кол-во колонок = " + pCol.ToString() + "\r\n");
                      err = hcSqlRowCount      (pOper, &pStr);     // Получить кол-во строк   результата
                      textBox_Copy3.AppendText("кол-во строк = " + pStr.ToString() + "\r\n");
                      err = hcSqlOpenResults   (pOper, &pRecSize); // Открытие результатов для чтения
                      textBox_Copy3.AppendText("размер записи = " + pRecSize.ToString() + "\r\n");
                
                      hcSqlDstInfoT[] infCol  =  new hcSqlDstInfoT[pCol]; // Структура "Информация о колонках результата"
                      
                      err = hcSqlGetStmtAttr(pOper, 107, 0,  infCol, (uint)pCol * 128 , &cntOp);// Получить информацию об операторе
                      
                      byte[] bufOut = new byte[pRecSize * pStr]; // Адрес буфера для присылаемых записей.
       
                      uint cntOut = 0;
       
                      err = hcSqlReadResults(pOper, 0, bufOut, pRecSize * (uint)pStr, &cntOut);// Чтение результатов
       
                      // byte  p = bufOut;
       
                      for (long i = 0; i < pStr; i++) // идем по строкам
                      {
       
                          for (int j = 0; j < pCol; ++j)// идем по колонкам
                          {
       
                              switch (infCol[j].type)// в зависимости от типа колонки преобразовываем в соответствующий тип
                              {
                                  case 0: // 0 Массив символов длиной не более заданной
                                         //string s(p, infCol[j].len);
                                         textBox_Copy3.AppendText( infCol[j].type  + " ");  
                                         break;
       
                      //            case 1: // 1 Массив байтов заданной длины
          //                        textBox_Copy3.AppendText(*reinterpret_cast < unsigned char *> (p) + " ");  
          //                               break;
       
                      //            case 2: // 2 Элемент - unsigned char (короткое целое)  short
          //                               std::cout << *reinterpret_cast < unsigned char*> (p) << "  ";
          //                               break;
       
                      //            case 3: // 3 Элемент - signed short  
          //                                     std::cout << *reinterpret_cast < signed short*> (p) << "  ";
          //                                break;
       
                      //case 4: // 4 Элемент - unsigned short  
          //        std::cout << *reinterpret_cast < unsigned short*> (p) << "  ";
          //        break;
       
                      //case 5: // 5 Дата    - unsigned short  
          //        std::cout << *reinterpret_cast < unsigned short*> (p) << "  ";
          //        break;
       
                      //case 6: //6  Номер   - 3-х байтовое целое без знака  
          //                                // std::cout << *reinterpret_cast<  *>(p);
          //        break;
       
                      //case 7: //7 Элемент - long int
          //        std::cout << *reinterpret_cast < long int*> (p) << "  ";
          //        break;
       
                      //case  8: // 8 Элемент - unsigned long int  в БД это dword          
          //        std::cout << *reinterpret_cast < unsigned long int*> (p) << "  ";
          //        break;
       
                      //case 9: //    9  Элемент - float
          //        std::cout << *reinterpret_cast<float*>(p) << "  ";
          //        break;
       
                      //case 10: //   10 Деньги (double)  
          //        std::cout << *reinterpret_cast<double*>(p) << "  ";
          //        break;
       
                      //case 1: // 11 Элемент - double  
          //        std::cout << *reinterpret_cast<double*>(p) << "  ";
          //        break;
       
                      //case 12: //   12 Элемент - signed __int64
          //        std::cout << *reinterpret_cast < signed __int64 *> (p) << "  ";
          //        break;
                      //case 13: //   13 Элемент - unsigned __int64
          //        std::cout << *reinterpret_cast < unsigned __int64 *> (p) << "  ";
          //        break;
              }
       
             // p += infCol[j].len;
       
              }
              textBox_Copy3.AppendText( "\r\n");  
          }
       
       
                      hcSqlCloseResults(pOper); // Закрытие доступа к результатам
       
                      hcSqlFreeConnect(pdb);    // Освободить соединение
       
                      hcSqlDone();              // Завершение работы
        
       
                  }
       
       
       
              }
       
       
       
       
       
       
          }
      }



    затык произошел на функции
    err = hcSqlReadResults(pOper, 0, bufOut, pRecSize * (uint)pStr, &cntOut);// Чтение результатов

    помогите пожалуйста разобраться с вопросом
    ошибку выдает такую
    ExpandedWrap disabled
      Помощник отладки управляемого кода "PInvokeStackImbalance" обнаружил неполадку в " \bin\x86\Debug\ComHyTech.vshost.exe".
       
      Дополнительные сведения: Вызов функции PInvoke "ComHyTech!ComHyTech.MainWindow::hcSqlReadResults" разбалансировал стек. Вероятно, это вызвано тем, что управляемая сигнатура PInvoke не совпадает с неуправляемой целевой сигнатурой. Убедитесь, что соглашение о вызовах и параметры сигнатуры PInvoke совпадают с неуправляемой целевой сигнатурой.


    Добавлено
    проект https://yadi.sk/d/Y5YtmjjK3GrG6f
      Помогите вопрос очень актуален
        Начать имеет смысл с явного задания в C#-сигнатуре того calling convention, который использует функция hcSqlReadResults в DLL
        https://msdn.microsoft.com/en-us/library/sy...(v=vs.110).aspx
          Всем спасибо вопрос решен
            Цитата Mr.Delphist @
            Начать имеет смысл с явного задания в C#-сигнатуре того calling convention, который использует функция hcSqlReadResults в DLL

            извините как то получилось что не прочитал Ваше сообщение, теперь начал разбиратся и немного не понял вот
            эти слова
            Цитата Mr.Delphist @
            C#-сигнатуре того calling convention, который использует функция hcSqlReadResults в DLL

            извините не очень силен поетому и переспрашиваю, что это значит и как это моно реализовать применительно к моему случаю

            на данный момент дошел вот до этого если будет интересно , https://github.com/vovakms/dbms-HyTech_edition_CSharp код закончен , только надо теперь оптимизировать и дорабатывать нюансы
              У каждой функции есть, кроме параметров и результата, так называемое "соглашение о вызовах". Оно определяет, в числе прочего, как используется стэк, кто ответственен за его менеджмент, в каком формате передаются параметры и результат. Поэтому попытка использовать функцию с иным calling convention, нежели с которым она скомпилирована, приведёт к ошибке (функция будет искать не там свои параметры, класть результат не туда, память будет либо утекать, либо дербаниться чужая).
              Например, сишные функции по умолчанию предполагают cdecl, однако WinAPI ставит в качестве стандарта stdcall.

              Подробнее:
              https://msdn.microsoft.com/en-us/library/984x0h58.aspx
                Цитата kms @
                Уважаемые форумчане , помогите с вопросом по использованию функций DLL(написана на Си) ,
                проект очень простенький все на одной кнопочке и пару текстЕдитов
                весь код линейный в одной кнопке

                Я же тебе еще в соседней теме, в этом разделе дал ссылки на нужную литературу. Если ты будешь вот так эспортировать каждую функцию - то выйдет громоздко, не красиво и не в ООП стиле. Я тебе предлагал написать класс обертку над этими функциями, потом его экспортировать в DLL

                ExpandedWrap disabled
                  class DLL_EXPORT MyClass
                  {...}

                Где DLL_EXPORT - это макрос, который в зависимости от режима будет равен либо __declspec(dllexport), либо __declspec(dllimport)

                Потом на С++/CLI набросать точно такой же класс, но который будет оберткой над этим классом:
                ExpandedWrap disabled
                  class MyWrapper
                  {
                  private:
                   MyClass m_myClass;
                  };

                Методы у него будут называться точно так же, по сути это внешне копия С++ класса, но в качестве реализации ты будешь просто вызывать методы своего С++ сного класса.
                А дальше, уже то, что у тебя получится на С++/CLI ты без всяких заморочек уже можешь использовать в C#
                Сообщение отредактировано: KILLER -
                  Цитата KILLER @
                  Я же тебе еще в соседней теме, в этом разделе дал ссылки на нужную литературу. Если ты будешь вот так эспортировать каждую функцию - то выйдет громоздко, не красиво и не в ООП стиле. Я тебе предлагал написать класс обертку над этими функциями, потом его экспортировать в DLL

                  Не-не-не, батенька, чтобы начать бегать и прыгать, надо научиться ходить. Давайте автор сперва твёрдо разберётся с экспортированием отдельных функций, а затем уже можно и классы попробовать экспортировать (не забывая про манглинг имён, ABI и прочие радости).
                    Цитата KILLER @
                    Я же тебе еще в соседней теме, в этом разделе дал ссылки на нужную литературу.

                    спасибо , литературу изучаю ,
                    Цитата KILLER @
                    Если ты будешь вот так эспортировать каждую функцию - то выйдет громоздко, не красиво и не в ООП стиле.

                    понять и простить

                    Цитата KILLER @
                    Я тебе предлагал написать класс обертку над этими функциями, потом его экспортировать в DLL

                    на С++ почти доделал , не хватает все времени и мозгов закончить , уже приготовил проекты и с одним классом и с двумя , делаю DLL-ку подключаю DLL-ку к тестовому проекту а оно че то не работает , я это дело пока оставил , еще на пару недель, а сейчас пока на С# пробую

                    Скрытый текст

                    Цитата KILLER @
                    де DLL_EXPORT - это макрос, который в зависимости от режима будет равен либо __declspec(dllexport), либо __declspec(dllimport)

                    Потом на С++/CLI набросать точно такой же класс, но который будет оберткой над этим классом:

                    class MyWrapper
                    {
                    private:
                     MyClass m_myClass;
                    };

                    Методы у него будут называться точно так же, по сути это внешне копия С++ класса, но в качестве реализации ты будешь просто вызывать методы своего С++ сного класса.
                    А дальше, уже то, что у тебя получится на С++/CLI ты без всяких заморочек уже можешь использовать в C#




                    я всетаки решил попробывать обойти С++/CLI , а сразу шпарить на С#, я подумал так если получится значит класс, если не получится так хоть немножко чето изучу , вот и по тихому там там по немногу собрал и вот что пулучилось и оно работает и вроде не плохо загляни на досуге глянь
                    https://github.com/vovakms/dbms-HyTech_edition_CSharp

                    Добавлено
                    Цитата Mr.Delphist @
                    Давайте автор сперва твёрдо разберётся с экспортированием отдельных функций, а затем уже можно и классы попробовать экспортировать

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

                    Цитата Mr.Delphist @
                    (не забывая про манглинг имён, ABI и прочие радости).

                    это для меня вооще дремучий лес

                    Добавлено
                    еще сейчас пытаюсь на github сделать доступ на редактирование гостям , но в интернете не где нету инфы , хочется сделать так чтобы любой зашел посмотрел и подправил , не регистрируясь на github, а так как гость

                    если вы в курсе как подскажите , или там только зарегиным надо быть чтобы редактировать ????
                      Ну у тебя Сшный подход к задаче на C#, я этот код уже видел на С++ в разделе С++. Просто у тебя вообще концептуально не верный подход конкретно на C#, поэтому и говорю, проще все вот эти потроха от базы спрятать в С++ класс. Ну а так, ты по сути не пользуешься плюшками C#, я бы наверное не делал всех этих циклов с добавлением рядков/колонок, обошолся каким нибудь BindingList'ом ну или что то подобное бы использовал, это ближе к C#, чем цикл. Да вот и саму гриду ты не так готовишь, опять же на биндингах было бы проще, создав класс/структуру с необходимыми полями. Пусть лучше шарписты что подскажут. Они лучше тут шарят.
                      Сообщение отредактировано: KILLER -
                        Цитата KILLER @
                        Ну у тебя Сшный подход к задаче на C#, я этот код уже видел на С++ в разделе С++.

                        да эт точно , я и не отрицаю у меня линейное мышление , я же чукча , что вижу то и пою (на полном серьезе без сарказма)

                        Цитата KILLER @
                        Ну а так, ты по сути не пользуешься плюшками C#, я бы наверное не делал всех этих циклов с добавлением рядков/колонок, обошолся каким нибудь BindingList'ом ну или что то подобное бы использовал, это ближе к C#, чем цикл

                        хоть маленький намек , или направление куда двигатся ,
                        дело в том что я начинал уже смотреть в сторону " Тип BindingList<T> предоставляет следующие члены."
                        только как обойти Т ему же надо задать тип , а в моем случае надо динамически разобрать динамический массив байтов и все это не зная заранее какие будут типы и размеры у полей

                        вот такие пироги , я уже не на первом форуме по десятому кругу объясняю , но наверное с меня плохой объяснялщик , или не кто наверное не разбирал байтовые массивы (без обид это я так к слову )

                        Цитата KILLER @
                        Пусть лучше шарписты что подскажут. Они лучше тут шарят.

                        их тут очень мало наверно , человек когда дорастает до определенного уровня , то уже не лазит по форумам, и тем более не отвечает на глупые вопросы, потому что думает "вот я же выучился познал таинство и мастерство кодера , и теперь эту тайну ни кому не скажу" :)

                        вот такие пироги (прошу прощения за свой Гарвардский )

                        Добавлено
                        Цитата KILLER @
                        Да вот и саму гриду ты не так готовишь, опять же на биндингах было бы проще, создав класс/структуру с необходимыми полями.

                        вот это я сейчас как раз и делаю , вот только что такое "биндингах "
                          Цитата kms @
                          только как обойти Т ему же надо задать тип , а в моем случае надо динамически разобрать динамический массив байтов и все это не зная заранее какие будут типы и размеры у полей

                          Создай структуру с типами колонок. У тебя есть БД, в ней есть таблицы - ты работаешь с этой БД - ты не знаешь типов данных и какие у нее колонки? Если так, значит БД не твоя, и ты пишешь всего лишь юзер интерфейс для работы с ее таблицами. Как ты узнал какие таблицы там есть ? Вообще странный подход.
                          В любом случае типы в таблице можно узнать. Далее создаешь свою структуру с нужными типами данных, передаешь ее в BindingList, связываешь его с таблицей, все. Примеры использования BindingList со всякими BindingSource и т.д. в интере есть полно.
                            Цитата kms @
                            вот это я сейчас как раз и делаю , вот только что такое "биндингах "

                            Ок, вот я накидал простенький пример, как примерно оно должно выглядеть у тебя, или по крайней мере как бы делал я:
                            Прикреплённый файлПрикреплённый файлBindings.zip (15,96 Кбайт, скачиваний: 110)

                            _data - это массив твоих структур, куда ты будешь вычитывать из БД инфу.

                            Добавлено
                            Так же, если внимательно посмотришь, то не увидишь где я гриде добавляю колонки. Они через DataSource автоматически берутся из типа ManGridData
                              Цитата KILLER @
                              Создай структуру с типами колонок.

                              не возможно , я не знаю типы колонок до момента выполнения запроса,

                              Цитата KILLER @
                              У тебя есть БД, в ней есть таблицы - ты работаешь с этой БД - ты не знаешь типов данных и какие у нее колонки?

                              я делаю клиентскую часть к СУБД HyTech как например "MySQL Workbench" или вообще универсальное средство "EMS SQL Management Studio"
                              т.е. я делаю менеджер управления не одной базы данных а клиентскую часть СУБД HyTech для того чтобы иметь доступ к самому ядру сервера СУБД чтобы создавать БазыДанных, таблицы и др.объекты СУБД, чтобы управлять не только БД а и самой СУБД, чтобы делать разные запросы на выборку не только с одной таблицы а настоящие запросы , HyTech поддерживает SQL-89 , вообщем все по настоящему все по взрослому

                              Добавлено
                              Цитата KILLER @
                              Ок, вот я накидал простенький пример, как примерно оно должно выглядеть у тебя, или по крайней мере как бы делал я:
                              Прикреплённый файлBindings.zip (15,96 Кбайт, скачиваний: 2)

                              ОК спасибо , посмотрел пример , но к сожалению это статика ,
                              как создавать типы динамически , во время выполнения программы , после получения ответа на SQL-запрос ?

                              Добавлено
                              если бы как то не так
                              ExpandedWrap disabled
                                public class ManGridData
                                    {
                                        public string Name { get; set; }
                                        public string City { get; set; }
                                        public string Street { get; set; }
                                 
                                        public string Billing { get; set; }
                                        public string Description { get; set; }
                                    }


                              а как бы в цикле если бы можно было задать вот абстрактный такой код ,
                              ExpandedWrap disabled
                                byte[]
                                 
                                // pCol - кол-во колонок результата  
                                 
                                bufOut = new byte[(int)wBufSize];   // буфер для результата
                                 
                                public class ClasPriemData ;// создать новый класс приемник под буфер
                                 
                                 for (int j=0; j< pCol; j++) // задаем поля класса приемника
                                {
                                 ClasPriemData.ДобавитьНовоеПолеСтипом = infCol[j].type ;  
                                }
                                 
                                ClasPriemData = bufOut ; // одним махом закидываем весь буфер в класс-приемник


                              если бы так сделать это бфло бы волшебство фантастика

                              Добавлено
                              Цитата KILLER @
                              Так же, если внимательно посмотришь, то не увидишь где я гриде добавляю колонки. Они через DataSource автоматически берутся из типа ManGridData

                              эт я понял
                              ExpandedWrap disabled
                                for (int i = 0; i < 50; ++i)
                                            {
                                                ManGridData dt = new ManGridData();
                                                dt.Name = "KILLER_" + i.ToString();
                                                dt.Street = "Beverly Hills_" + i.ToString();
                                                dt.City = "USA_" + i.ToString();
                                                dt.Billing = "12345567788_" + i.ToString();
                                                dt.Description = "Description_" + i.ToString();
                                 
                                                _data.Add(dt);
                                            }
                              Сообщение отредактировано: kms -
                                Цитата kms @
                                их тут очень мало наверно , человек когда дорастает до определенного уровня , то уже не лазит по форумам, и тем более не отвечает на глупые вопросы, потому что думает "вот я же выучился познал таинство и мастерство кодера , и теперь эту тайну ни кому не скажу" :)

                                не шарписты как правило это молодняк, который сразу начал с C#, так что они просто не знают как быть в твоём случае ;)
                                  Цитата Cfon @
                                  так что они просто не знают как быть в твоём случае

                                  да эт точно , я нашел на другом форуме человека
                                    Цитата kms @
                                    как создавать типы динамически , во время выполнения программы , после получения ответа на SQL-запрос ?

                                    Ну самое простое создать отдельно либо класс либо метод, который будет конвертировать поле в нужный тип. Информация о типе то у тебя есть.
                                    Просто проблема в том, что ты делаешь задачу, не изучив даже инструмент, с которым работаешь. Хотя в C# думаю средствами языка можно сделать преобразование типов на лету.
                                      Цитата KILLER @
                                      Информация о типе то у тебя есть.

                                      да да да есть в infCol[n].type на каждый столбик

                                      Цитата KILLER @
                                      Просто проблема в том, что ты делаешь задачу, не изучив даже инструмент, с которым работаешь.

                                      ну тут уж че поделаешь , все на ходу , прошу не судить строго
                                      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                      0 пользователей:


                                      Рейтинг@Mail.ru
                                      [ Script execution time: 0,0736 ]   [ 19 queries used ]   [ Generated: 29.03.24, 14:37 GMT ]