Ruby Sketchup Error when calling dll library in Sketchup Ruby - ruby

I want Sketchup can import muliple files. But unfortunately, Sketchup API dosen't support it. So i created one dll library. It call Window API function: GetOpenFileName for displaying multi-select dialog, get selected file names and display them in formatted string (selected directory | filename1 |filename2...). Then i put it and Win32API.so into Plugin folder of Sketchup. But when i open Sketchup, it display error: Error Loading File GetProcAddress: ShowDialog or ShowDialogA (ShowDialog is one function of my dll )
Here is my code in dllmain.cpp (C++ code)
#define EXPORT _declspec(dllexport)
HWND hDlg = NULL;
wchar_t* buffer = new wchar_t[32768];
EXPORT void ShowDialog(void)
{
OPENFILENAME ofn;
wchar_t szFile[32768];
// Initialize OPENFILENAME
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hDlg;
ofn.lpstrFile = (wchar_t*)szFile;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_ALLOWMULTISELECT | OFN_ENABLESIZING | OFN_EXPLORER;
if(GetOpenFileName(&ofn) == TRUE)
{
if(szFile[ofn.nFileOffset-1] != '\0')
{
wcscpy_s(buffer,sizeof(szFile),szFile);
}
else
{
//Multi-select
wchar_t* p= szFile;
int i =0;
while(*p)
{
wchar_t* temp = new wchar_t[1024];
//Copy p into temp
wcscpy_s(temp,1024,p);
if(i==0)
{
wcscpy_s(buffer,1024,temp);
}
else
{
wcscat_s(buffer,1024,temp);
}
wcscat_s(buffer, sizeof(buffer) * wcslen(buffer), L"|");
i++;
p += lstrlen(p) + 1;
}
}
int len = wcslen(buffer);
buffer[len]='\0';
}
EXPORT void GetResult(char* pString)
{
int len = wcslen(buffer);
for(int i =0 ; i < wcslen(buffer);i++)
{
pString[i] = (char)buffer[i];
}
pString[len]='\0';
}
Here is my script in ruby file.
require 'sketchup.rb'
require "Win32API"
path = Sketchup.find_support_file("\Plugins\\")
#my dll has name MultiUploadProject.dll
mydll = path + "\\MultiUploadProject.dll"
if (!FileTest.exist?( mydll ) )
UI.messagebox(sprintf("MultiUploadProject.dll not found in SketchUp plugins folder: %s\n",mydll))
end
ShowDialog = Win32API.new(mydll,"ShowDialog",["V"],"V")
GetResult = Win32API.new(mydll,"GetResult",["P"],"V")
def load_dialog
ShowDialog.call
string = " " * 32768
GetResult.call(string)
end
I use Visual Studio 2012 to build dll and My Sketchup is Sketchup 8
Any suggestions would be appreciated.

The export needs to be C exports (without C++ name mangling). Try defining the EXPORT macro like this:
#define EXPORT extern "C" _declspec(dllexport)
or define the exported functions inside extern "C"
extern "C" {
// Exported functions here.
}

Related

File Name Path Bug

I'm starting to program and I'm using Visual Studio. I have this simple program that some days ago worked, but after working with another project, it now returns me an error:
// Include file header
#include <Windows.h>
#include <iostream>
#include <sstream>
#include <string>
#include <string.h>
#include <gif_lib.h>
void SaveDialogCreation(HWND hWnd)
{
OPENFILENAMEA ofn;
char szFileName[MAX_PATH] = "";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.lpstrFilter = "Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrDefExt = "txt";
ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
// open save dialog
if (GetSaveFileNameA(ofn))
{
gif_write(szFileName);
}
}
//gif_write code function
bool gif_write(const char *fileName)
{
// it using giflib_win library
int error;
// Open gif file
GifFileType* gifFile = EGifOpenFileName(fileName, false, &error);
// error while open gif file
if (!gifFile) {
std::cout << "EGifOpenFileName() failed - " << error << std::endl;
return false;
}
GifColorType colors[64];
GifColorType* c = colors;
int level[4] = { 0, 85, 170, 255 };
for (int r = 0; r < 4; ++r) {
for (int g = 0; g < 4; ++g) {
for (int b = 0; b < 4; ++b, ++c) {
c->Red = level[r];
c->Green = level[g];
c->Blue = level[b];
}
}
}
// Write pixel to gif
GifByteType pix[16] = {
0, 1, 2, 3, // B
0, 4, 8, 12, // G
0, 16, 32, 48, // R
0, 21, 42, 63, // BK
};
gifFile->SWidth = 4;
gifFile->SHeight = 4;
gifFile->SColorResolution = 8;
gifFile->SBackGroundColor = 0;
gifFile->SColorMap = GifMakeMapObject(64, colors);
SavedImage gifImage;
gifImage.ImageDesc.Left = 0;
gifImage.ImageDesc.Top = 0;
gifImage.ImageDesc.Width = 4;
gifImage.ImageDesc.Height = 4;
gifImage.ImageDesc.Interlace = false;
gifImage.ImageDesc.ColorMap = nullptr;
gifImage.RasterBits = (GifByteType*)malloc(16);
gifImage.ExtensionBlockCount = 0;
gifImage.ExtensionBlocks = nullptr;
memcpy(gifImage.RasterBits, pix, 16);
GifMakeSavedImage(gifFile, &gifImage);
if (EGifSpew(gifFile) == GIF_ERROR) {
std::cout << "EGifSpew() failed - " << gifFile->Error << std::endl;
EGifCloseFile(gifFile, &error);
return false;
}
// Close gif file
EGifCloseFile(gifFile, &error);
return true;
}
I can compile it, but when I use the save dialog in gif_write(), it saves the gif file but has the first character in the filename.
How can I solve this?
It can compile but crashed.
It's definite that there is a semantic problem with the code. A possible one is OFN_EXPLORER which Indicates that
any customizations made to the Open or Save As dialog box. By default,
the Open and Save As dialog boxes use the Explorer-style user
interface regardless of whether this flag is set. This flag is
necessary only if you provide a hook procedure or custom template,
or set the OFN_ALLOWMULTISELECT flag.
You could need the example.

FFmpeg avutil.lib unresolved external symbol

i'm trying to use FFmpeg with visual sudio 2022 .NET 6 through an MSVC project.
I followed this tutorial: https://www.youtube.com/watch?v=qMNr1Su-nR8&ab_channel=HakanSoyalp.
I mean I have configureg Include (.h) file, library (.lib) files and dynamic (.dll) file copied into bin folder.
If I call for example the avformat_alloc_context() method inside the avformat.lib all work rightly, if I call for example av_file_map(...) inside the avutil.lib the compiler give me an error:
LNK2019 unresolved external symbol "int __cdecl av_file_map ...
But the avutil.lib is linked!!!
The same happen if I call other methods inside avutil.lib module.
Thanks for help...
Code:
extern "C"
{
#include <libavformat/avformat.h>
#include <libavutil/file.h> // av_file_map
}
int ConvertJPEGtoNALs(int argc, char* argv[])
{
AVFormatContext* fmt_ctx = NULL;
AVIOContext* avio_ctx = NULL;
uint8_t* buffer = NULL, * avio_ctx_buffer = NULL;
size_t buffer_size, avio_ctx_buffer_size = 4096;
char* input_filename = NULL;
int ret = 0;
struct buffer_data bd = { 0 };
if (argc != 2) {
fprintf(stderr, "usage: %s input_file\n"
"API example program to show how to read from a custom buffer "
"accessed through AVIOContext.\n", argv[0]);
return 1;
}
input_filename = argv[1];
/* register codecs and formats and other lavf/lavc components*/
//av_register_all(); //!deprecated
/* slurp file content into buffer */
ret = av_file_map(input_filename, &buffer, &buffer_size, 0, NULL);
/* fill opaque structure used by the AVIOContext read callback */
bd.ptr = buffer;
bd.size = buffer_size; ???
if (!(fmt_ctx = avformat_alloc_context())) {
ret = AVERROR(ENOMEM);
goto end;
}
//... to be continue ...
}

How to send hardware keyboard or mouse press using any programming language?

I found a lot of answers about this question that works in notepad and other programs but doesn't work in a specific game!
it seems that the game block the inputs from my program.
here is the programs that I have tried.
1- using SendInput (c++)
#include <future>
#include<Windows.h>
using namespace std::chrono;
using namespace std::this_thread;
using namespace std;
UINT PressKeyScan(WORD scanCode)
{
INPUT input[1] = { 0 };
input[0].type = INPUT_KEYBOARD;
input[0].ki.wVk = NULL;
input[0].ki.wScan = scanCode;
input[0].ki.dwFlags = KEYEVENTF_SCANCODE ;
UINT ret = SendInput(1, input, sizeof(INPUT));
return ret;
}
UINT ReleaseKeyScan(WORD scanCode)
{
INPUT input[1] = { 0 };
input[0].type = INPUT_KEYBOARD;
input[0].ki.wVk = NULL;
input[0].ki.wScan = scanCode;
input[0].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
UINT ret = SendInput(1, input, sizeof(INPUT));
return ret;
}
int main()
{
for (size_t i = 0; i < 100; i++)
{
PressKeyScan(0x39);
sleep_for(milliseconds(100));
ReleaseKeyScan(0x39);
sleep_for(milliseconds(100));
}
}
2- using SendKeys (C# winforms)
private void btnSendKeys_Click(object sender, EventArgs e)
{
int iHandle = NativeWin32.FindWindow(null, txtTitle.Text);
NativeWin32.SetForegroundWindow(iHandle);
string keys = "";
string space = " ";
for (int i = 0; i < lbKeys.Items.Count; i++)
{
if (lbKeys.Items[i].Text.ToString() == "{SPACE}")
{
keys += space;
}
else
{
keys += lbKeys.Items[i].Text.ToString();
}
}
System.Windows.Forms.SendKeys.Send(keys);
}
both worked in notepad and some other apps but didn't worked in specific game.
I have tried to run the program as administrator and it finally works :D

Crash in Win32 App while calling "GetOpenFileName"

I have one win32 prog where i want to call GetOpenFileName() but every time it got crash and CommDlgExtendedError() return error code as 1008. Please help me out.
char Filestring[MAX_PATH] = "\0";
OPENFILENAME ofn = { 0 };
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.lpstrFile = (LPWSTR)Filestring;
ofn.nMaxFile = MAX_PATH;
if (GetOpenFileName(&ofn) == TRUE)
{
}
else
{
int err = CommDlgExtendedError();
}
You are using the TCHAR version of the GetOpenFileName() API, which maps to either the ANSI (GetOpenFileNameA()) or Unicode (GetOpenFileNameW()) API depending on whether UNICODE is defined.
Since ofn.lpstrFile is accepting a LPWSTR (wchar_t*) pointer, expecting it to point at a wchar[] buffer, your project clearly has UNICODE defined. But you are giving it a type-casted pointer to a char[] buffer instead, which has 1/2 the storage space than you are telling the API is available for it to write to.
Your type-cast on the ofn.lpstrFile field is lying to the API. The code is calling the Unicode API, so it will write Unicode data to your char[] buffer, giving you mojibake output, and risking a buffer overflow.
You should use a TCHAR[] buffer instead to match what the API is expecting, eg:
TCHAR Filestring[MAX_PATH] = TEXT("\0");
OPENFILENAME ofn = { 0 };
ofn.lStructSize = sizeof(ofn);
ofn.lpstrFile = Filestring;
ofn.nMaxFile = MAX_PATH;
if (GetOpenFileName(&ofn))
{
...
}
else
{
int err = CommDlgExtendedError();
...
}
Otherwise, use the ANSI or Unicode API explicitly, depending on your desired character encoding, eg:
CHAR Filestring[MAX_PATH] = "\0";
OPENFILENAMEA ofn = { 0 };
ofn.lStructSize = sizeof(ofn);
ofn.lpstrFile = Filestring;
ofn.nMaxFile = MAX_PATH;
if (GetOpenFileNameA(&ofn))
{
...
}
else
{
int err = CommDlgExtendedError();
...
}
WCHAR Filestring[MAX_PATH] = L"\0";
OPENFILENAMEW ofn = { 0 };
ofn.lStructSize = sizeof(ofn);
ofn.lpstrFile = Filestring;
ofn.nMaxFile = MAX_PATH;
if (GetOpenFileNameW(&ofn))
{
...
}
else
{
int err = CommDlgExtendedError();
...
}

Win32 function to OpenFileDialog?

I searching function something like OpenFileDialog on .NET but on win32, i can't find this function on this name on msdn and i remember this function exists.
Can anyone give me name?
Greetings,
I believe you are looking for the GetOpenFileName.
//make sure this is commented out in all code (usually stdafx.h)
// #define WIN32_LEAN_AND_MEAN
#include <windows.h>
OPENFILENAME ofn; // common dialog box structure
TCHAR szFile[260] = { 0 }; // if using TCHAR macros
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = _T("All\0*.*\0Text\0*.TXT\0");
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetOpenFileName(&ofn) == TRUE)
{
// use ofn.lpstrFile
}
Taken from Displaying Open File Dialog using WinApi

Resources