Возвращаем строку из функции C++ библиотеки в VBA
Не так давно передо мной встал вопрос, как из VBA (Visual Basic for Application), который используется в Excel, Word и других приложениях офиса от Microsoft, вызвать функцию из библиотеки, написанной на C++, и получить на выходе строку. Причём строка должна содержать кириллические символы и всё это должно работать как на 32-битных, так и на 64-битных системах Windows. Предлагаю здесь найденное решение, которое одинаково хорошо работает со всеми версиями офиса.
После изучения документации стало понятно, что для типа String в VBA используется кодировка ASCII. Причём первые 4 байта - это длина строки. Т.е. можно конечно создать строку, которую поймёт Excel, и вернуть её, но я нигде не нашёл ничего про соглашение, кто должен удалять созданный буфер со строкой и каким образом. Поэтому так лучше не делать.
Лучше возвращать строки так, как это принято делать в C: наша функция должна принять на вход указатель на буфер, куда нужно скопировать строку, и размер этого буфера, затем скопировать строку в буфер и вернуть количество скопированных символов. Причём, если нам передали длину буфера 0, то мы должны только посчитать и вернуть размер строки, не записывая ничего в буфер. Вот как это будет выглядеть (пример сделан на Embarcadero C++Builder):
Вызвать такую функцию из VBA можно двумя способами. Первый способ – это когда мы примерно предполагаем, что длина строки не может быть больше какого-то размера. Или нам достаточно считать только начало строки. В этом случае можем не запрашивать размер строки, а сразу пытаться получить строку нужного размера. Макрос в Excel будет выглядеть так:
Второй способ – это определение размера строки и только потом её получение. В этом случае нашу функцию get_text придётся вызывать два раза. Вот пример макроса в Excel: